Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C语言中函数列表的动态调度方法_C - Fatal编程技术网

C语言中函数列表的动态调度方法

C语言中函数列表的动态调度方法,c,C,我尝试用各种方法计算RGB像素的亮度,使用C99和GCC 9。我有这个枚举: typedef enum dt\u iop\u toneequalizer\u方法 { DT_TONEEQ_平均值=0, DT_TONEEQ_亮度, DT_TONEEQ_值 }dt_iop_toneequalizer_method_t; 这是来自GUI的用户输入 然后,我有几个对应于每种情况的函数: typedef浮点rgb_像素[4]_属性__((对齐(16)); #pragma omp声明simd对齐(像素:64

我尝试用各种方法计算RGB像素的亮度,使用C99和GCC 9。我有这个枚举:

typedef enum dt\u iop\u toneequalizer\u方法
{
DT_TONEEQ_平均值=0,
DT_TONEEQ_亮度,
DT_TONEEQ_值
}dt_iop_toneequalizer_method_t;
这是来自GUI的用户输入

然后,我有几个对应于每种情况的函数:

typedef浮点rgb_像素[4]_属性__((对齐(16));
#pragma omp声明simd对齐(像素:64)
静态浮点RGB平均值(常量RGB像素)
{
返回(像素[0]+像素[1]+像素[2]+像素[3])/3.0f;
}
#pragma omp声明simd对齐(像素:16)
静态浮点RGB_值(常量RGB_像素)
{
返回fmaxf(fmaxf(像素[0],像素[1]),像素[2]);
}
#pragma omp声明simd对齐(像素:16)
静态浮点RGB亮度(常量RGB像素)
{
常量浮点最大值(像素)=(像素);
const float min_rgb=fminf(像素[0],fminf(像素[1],像素[2]);
返回(最大rgb+最小rgb)/2.0f;
}
然后,图像上的循环是:

static void exposure\u mask(常量浮点*常量限制输入),
浮点*常量限制输出,
const size\u t width,
施工尺寸和高度,
常数dt_iop_toneequalizer_方法(t方法)
{
#pragma omp并行用于simd默认(无)计划(静态)对齐(输入、输出:64)
用于(尺寸k=0;k<4*宽*高;k+=4)
{
const rgb_pixel pixel={in[k],in[k+1],in[k+2],0.0f};
out[k/4]=RGB_光(像素,方法);
}
}
我的第一种方法是使用带有开关/案例映射的
RGB_light()
函数来映射
方法和函数,但这会触发对每个像素的检查,这相当昂贵

我的想法是使用方法的列表或结构,如:

typedef struct RGB_light
{
  // Pixel intensity (method == DT_TONEEQ_MEAN)
  float (*_RGB_mean)(rgb_pixel pixel);

  // Pixel HSL lightness (method == DT_TONEEQ_LIGHTNESS)
  float (*_RGB_lightness)(rgb_pixel pixel);

  // Pixel HSV value (method == DT_TONEEQ_VALUE)
  float (*_RGB_value)(rgb_pixel pixel);
} RGB_light;
typedef结构RGB_灯
{
//像素强度(方法==DT\u TONEEQ\u平均值)
浮点(*_RGB_平均值)(RGB_像素);
//像素HSL亮度(方法==DT_TONEEQ_亮度)
浮点(*_RGB_亮度)(RGB_像素);
//像素HSV值(方法==DT\u TONEEQ\u值)
浮点(*_RGB_值)(RGB_像素);
}RGB_灯;
然后在循环之前一次性初始化该方法,如

static void exposure\u mask(常量浮点*常量限制输入),
浮点*常量限制输出,
const size\u t width,
施工尺寸和高度,
常数dt_iop_toneequalizer_方法(t方法)
{
lightness_method=RGB_light[method];//语法明显错误
#pragma omp并行用于simd默认(无)计划(静态)对齐(输入、输出:64)
用于(尺寸k=0;k<4*宽*高;k+=4)
{
const rgb_pixel pixel={in[k],in[k+1],in[k+2],0.0f};
out[k/4]=亮度法(像素);
}
}
但我并没有成功地将这个想法转化为实际的工作代码

有一点类似于我想在Python中执行的操作:

def RGB_值(像素):
还什么
def RGB_亮度(像素):
还什么
方法={1:RGB_值,2:RGB_亮度}
def循环(图像、方法):
对于图像中的像素:
亮度=方法[方法](像素)

问题的关键似乎是:

我的想法是使用方法的列表或结构,如:

typedef struct RGB_light
{
  // Pixel intensity (method == DT_TONEEQ_MEAN)
  float (*_RGB_mean)(rgb_pixel pixel);

  // Pixel HSL lightness (method == DT_TONEEQ_LIGHTNESS)
  float (*_RGB_lightness)(rgb_pixel pixel);

  // Pixel HSV value (method == DT_TONEEQ_VALUE)
  float (*_RGB_value)(rgb_pixel pixel);
} RGB_light;
然后在循环之前一次性初始化该方法,如

static void exposure_mask(const float *const restrict in, 
                          float *const restrict out,
                          const size_t width, 
                          const size_t height, 
                          const dt_iop_toneequalizer_method_t method)
{
  lightness_method = RGB_light[method]; // obviously wrong syntax
,实际问题是使用什么,而不是“明显错误的语法”。但是您已经清楚地知道如何声明函数指针,并且描述了基于
方法切换的其他代码。把这些放在一起的自然方式是

    float (*lightness_method)(rgb_pixel pixel);

    switch (method) {
        case DT_TONEEQ_MEAN:
            lightness_method = _RGB_mean;
            break;
        case DT_TONEEQ_LIGHTNESS:
            lightness_method = _RGB_lightness;
            break;
        case DT_TONEEQ_VALUE:
            lightness_method = _RGB_value;
            break;
    }
。。。你会在以后的某个地方用一些类似于

        float l = lightness_method(one_pixel);
如果在任何数组中而不是在结构中提供“方法”,则类似情况也适用,在这种情况下,可以使用
method
变量而不是使用
switch
语句对数组进行索引

但是,请注意,由于您似乎专注于性能,因此您可能会发现,沿着这些思路的任何方法都有点平淡无奇。通过指针间接调用函数会拒绝编译器进行优化的机会,尽管在像素上的循环外解析特定函数指针可能会带来改进,但间接寻址本身可能比重复查找更能导致性能不满意


您应该考虑将代码导入到 SurvivyMask]()/COD>的多个版本中,每个版本都直接调用一个特定的亮度函数。至少要考虑测试这样的安排。另外,因为你将需要一组基本相同的函数,你可以考虑使用宏或程序代码生成器来生成它们,而不是手工编写和维护所有这些变型。

< P>基于约翰·布林格的回答,我尝试了:

定义循环(fn)\ { \ _Pragma(“omp并行用于simd默认(无)计划(静态)\ firstprivate(宽度、高度、通道、入口、出口)\ 对齐(输入、输出:64)”\ 用于(尺寸k=0;k