如何在线程安全C库中高效地实现句柄
我有一个相当复杂的C99兼容共享库。它包含大量全局变量和许多短函数,但只有少数函数可供用户直接使用 我想把它重构成一个线程安全的库。为此,我将让用户向每个函数传递一个句柄。句柄将是指向结构的指针,该结构包含以前的全局变量 在这种情况下,性能很重要,我不想破坏它。在实现句柄时,我需要注意什么?例如,一个典型的函数如下所示如何在线程安全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
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
是指针,那么编译器就无法对其进行优化。如果它是一个成员数组,那么它就会。