Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.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_Multithreading_Optimization_Shared Libraries_C99 - Fatal编程技术网

如何在线程安全C库中高效地实现句柄

如何在线程安全C库中高效地实现句柄,c,multithreading,optimization,shared-libraries,c99,C,Multithreading,Optimization,Shared Libraries,C99,我有一个相当复杂的C99兼容共享库。它包含大量全局变量和许多短函数,但只有少数函数可供用户直接使用 我想把它重构成一个线程安全的库。为此,我将让用户向每个函数传递一个句柄。句柄将是指向结构的指针,该结构包含以前的全局变量 在这种情况下,性能很重要,我不想破坏它。在实现句柄时,我需要注意什么?例如,一个典型的函数如下所示 void calculate(){ for (int i=0; i<N; i++){ particle[i].x += G * particl

我有一个相当复杂的C99兼容共享库。它包含大量全局变量和许多短函数,但只有少数函数可供用户直接使用

我想把它重构成一个线程安全的库。为此,我将让用户向每个函数传递一个句柄。句柄将是指向结构的指针,该结构包含以前的全局变量

在这种情况下,性能很重要,我不想破坏它。在实现句柄时,我需要注意什么?例如,一个典型的函数如下所示

void calculate(){
    for (int i=0; i<N; i++){   
        particle[i].x += G * particle[i].y;
        other_function_that_does_something_to_particle();
    }
}
void calculate(struct Handle* h){
    for (int i=0; i<h->N; i++){   
        h->particle[i].x += h->G * h->particle[i].y;
        other_function_that_does_something_to_particle(h);
    }
}
void计算(){
对于(inti=0;iparticle[i].x+=h->G*h->particle[i].y;
对粒子(h)做某事的其他函数;
}
}

这看起来效率很低。有更好的方法吗?

传递指针的成本通常很低。它对架构有更大的影响,其中参数通过堆栈传递,而当参数通过寄存器传递时,影响会更小

使用
const
指针(指向const数据的指针)。当数据可以被其他线程修改时,使用
volatile
字段或指针说明符。并使用
restrict

所有类型说明符都有一定的影响。例如,当处理多个引用而不使用
restrict
,编译器可能会被迫重新读取值,即使它已经读取了这些值。等等


值得一读:

这并不一定慢。在某些体系结构上,它甚至可以更快,因为它们必须将全局变量的地址加载到寄存器中(例如ARM)。只需检查平台的PC和ABI,以确保参数的最佳传递方式,以便在寄存器中传递句柄/上下文指针

我会使
h
本身保持不变,但是:
struct Handle*const h
。这可以防止
h
被意外修改


如果您可以移动到C11,请查看_Thread_local storage class specifier。这可能是您想要的。但是,如果手动实现可能更有效,则取决于您的系统。

除非由线程共享,否则不需要
volatile
。常量
指针是常量指针,而不是指向常量数据的指针a、 在上面的例子中,本地缓存常量(例如
constdouble\u g=h->g
)有意义吗?@hanno:我会先尝试不缓存。让编译器先进行优化。像gcc这样的现代编译器通常比您更清楚如何处理其目标体系结构。只有在性能不足的情况下,才确定热点并进行操作手动优化。是的,这是有意义的。编译器并不总是能够找出
h->G
h->particle[i].x
不同。但是如果它是,那么额外的变量就没有效果。@Olaf如果
h->particle
是指针,那么编译器就无法对其进行优化。如果它是一个成员数组,那么它就会。