Macros 如何在OpenCL中使用宏替换/注入函数调用

Macros 如何在OpenCL中使用宏替换/注入函数调用,macros,opencl,pyopencl,Macros,Opencl,Pyopencl,我正在使用PyOpenCL开发一个算法。为了避免代码重复,我尝试使用模板和C宏来替换函数调用,因为OpenCL1.2不支持函数指针 我目前在OpenCL内核代码中有以下宏部分: #define LINEAR_FIT_SEARCH_METHOD ${linear_fit_search_method} #if LINEAR_FIT_SEARCH_METHOD == MIN_MAX_INTENSITY_SEARCH #define LINEAR_FIT_SEARCH_METHOD_CALL() de

我正在使用PyOpenCL开发一个算法。为了避免代码重复,我尝试使用模板和C宏来替换函数调用,因为OpenCL1.2不支持函数指针

我目前在OpenCL内核代码中有以下宏部分:

#define LINEAR_FIT_SEARCH_METHOD ${linear_fit_search_method}

#if LINEAR_FIT_SEARCH_METHOD == MIN_MAX_INTENSITY_SEARCH
#define LINEAR_FIT_SEARCH_METHOD_CALL() determineFitUsingMinMaxIntensitySearch(lineIntensities,imgSizeY,linFitParameter,linFitSearchRangeXvalues)
#elif LINEAR_FIT_SEARCH_METHOD == MAX_INCLINE_SEARCH
#define LINEAR_FIT_SEARCH_METHOD_CALL() determineFitUsingInclineSearch(lineIntensities,imgSizeY,linFitParameter,linFitSearchRangeXvalues,inclineRefinementRange)
#endif
在内核代码中,我还定义了相应的函数
determineFitUsingMinMaxIntensitySearch
determinefitusingclinesearch
。我现在尝试使用宏来交换函数调用,如下所示:

__private struct linearFitResultStruct fitResult = LINEAR_FIT_SEARCH_METHOD_CALL();
def applyTemplating(self):
    tpl = Template(self.kernelString)
    if self.positioningMethod == "maximumIntensityIncline":
        linear_fit_search_method="MAX_INCLINE_SEARCH"
    if self.positioningMethod == "meanIntensityIntercept":
        linear_fit_search_method="MIN_MAX_INTENSITY_SEARCH"
    rendered_tpl = tpl.render(linear_fit_search_method=linear_fit_search_method)
    self.kernelString=str(rendered_tpl)
因此,我选择所需的调用(注意:我总是只需要其中一个调用,并且在程序运行之前完成配置(不需要动态切换这两个调用))

使用PyOpenCL模板,我现在可以执行以下操作:

__private struct linearFitResultStruct fitResult = LINEAR_FIT_SEARCH_METHOD_CALL();
def applyTemplating(self):
    tpl = Template(self.kernelString)
    if self.positioningMethod == "maximumIntensityIncline":
        linear_fit_search_method="MAX_INCLINE_SEARCH"
    if self.positioningMethod == "meanIntensityIntercept":
        linear_fit_search_method="MIN_MAX_INTENSITY_SEARCH"
    rendered_tpl = tpl.render(linear_fit_search_method=linear_fit_search_method)
    self.kernelString=str(rendered_tpl)
其中
self.kernelString
包含上述宏以及代码

不幸的是,我得到了这个错误,我不理解:

1:455:53:错误:函数“DetermineFitusingClineSearch”的隐式声明在OpenCL中无效 1:9:41:注意:从宏“线性拟合搜索方法调用”展开 1:455:41:错误:使用不兼容类型“int”的表达式初始化“struct LinearFirtResultStruct” 1:536:30:错误:“DetermineFitusingClineSearch”的类型冲突 1:455:53:注意:前面的隐式声明在这里 1:9:41:注意:从宏“线性拟合搜索方法调用”展开 1:616:41:错误:使用不兼容类型“int”的表达式初始化“struct LinearFirtResultStruct”

我很少使用宏,因此:

我所尝试的是以这种方式实现的,还是我需要走另一条路

更新1: 当我在单元测试中设置
self.positioningMethod=“meanIntensityIntercept”
时,此代码运行正常,但在设置
self.positioningMethod=“maximumIntensityIncline”
时失败,并显示上述错误消息。我现在还不能发现这个错误

更新2: 我也受到了这篇文章的启发,如果这有帮助的话:

正如你所说,你对宏几乎没有经验,那么我会选择一些简单的东西
determineFitUsingMinMaxIntensitySearch
determinefitusingclinesearch
接受不同数量的参数,因此可以通过以下方式完成:

kernel_code = """

#ifdef USE_FUNCTION_A

void function_a(
    int x,
    int y,
    int extra_param,
    __global const int* restrict in,
    __global int* restrict out
)
{
    //...
}

#else

void function_b(
    int x,
    int y,
    __global const int* restrict in,
    __global int* restrict out
)
{
    //...
}

#endif

__kernel void my_kernel(
    int x,
    int y,
    __global const int* restrict in,
    __global int* restrict out
)
{
    // ...
#ifdef USE_FUNCTION_A
    function_a(x,y,5,in,out);
#else
    function_b(x,y,in,out);
#endif
    // ...
}
"""

if use_function_a:
    prg = cl.Program(ctx, kernel_code).build("-DUSE_FUNCTION_A")
else:
    prg = cl.Program(ctx, kernel_code).build("")

正如你所说,你对宏几乎没有经验,那么我会选择一些简单的东西
determineFitUsingMinMaxIntensitySearch
determinefitusingclinesearch
接受不同数量的参数,因此可以通过以下方式完成:

kernel_code = """

#ifdef USE_FUNCTION_A

void function_a(
    int x,
    int y,
    int extra_param,
    __global const int* restrict in,
    __global int* restrict out
)
{
    //...
}

#else

void function_b(
    int x,
    int y,
    __global const int* restrict in,
    __global int* restrict out
)
{
    //...
}

#endif

__kernel void my_kernel(
    int x,
    int y,
    __global const int* restrict in,
    __global int* restrict out
)
{
    // ...
#ifdef USE_FUNCTION_A
    function_a(x,y,5,in,out);
#else
    function_b(x,y,in,out);
#endif
    // ...
}
"""

if use_function_a:
    prg = cl.Program(ctx, kernel_code).build("-DUSE_FUNCTION_A")
else:
    prg = cl.Program(ctx, kernel_code).build("")

C宏复制代码。如果您担心代码密度,请信任编译器并编写正确的函数。我不确定是否理解您的观点。我尝试的是使用宏“注入”函数调用,以在另一个函数中修改该调用的行为。这是必要的,因为函数指针在OpenCL1.2下不可用。一个相关的帖子是这样的:事实证明,上面提出的方法正如预期的那样有效。问题是,两种方法中的一种(通过“注入”宏)证明上述方法可以按预期工作。问题是,当使用宏“注入”函数时,两个函数中的一个是在第一次引用该函数之后定义的。这就是注入第一个函数有效而第二个函数无效(第一次调用后定义的函数)的原因。我不确定是否应该将此作为答案发布,因为问题与宏本身无关,其他人无法使用提供的信息找到问题的解决方案…C宏复制代码。如果您担心代码密度,请信任编译器并编写正确的函数。我不确定是否理解您的观点。我尝试的是使用宏“注入”函数调用,以在另一个函数中修改该调用的行为。这是必要的,因为函数指针在OpenCL1.2下不可用。一个相关的帖子是这样的:事实证明,上面提出的方法正如预期的那样有效。问题是,两种方法中的一种(通过“注入”宏)证明上述方法可以按预期工作。问题是,当使用宏“注入”函数时,两个函数中的一个是在第一次引用该函数之后定义的。这就是注入第一个函数有效而第二个函数无效(第一次调用后定义的函数)的原因。我不确定是否应该将此作为答案发布,因为问题与宏本身无关,其他人无法使用提供的信息找到问题的解决方案。。。