0xd*_*00d 3 c multithreading initialization
例如,我正在编写一个库函数,count_char(const char *str, int len, char ch)它检测正在运行的 CPU 支持的 SIMD 扩展并将调用分派到 AVX2 或 SSE4.2 优化版本。因为我想避免cpuid每次调用执行几个指令的惩罚,所以我试图在第一次调用函数时只执行一次(可能由不同的线程同时调用)。
在 C++ 领域,我只会做类似的事情
int count_char(const char *str, int len, char ch) {
static const auto fun_ptr = select_simd_function();
return (*fun_ptr)(str, len, ch);
}
Run Code Online (Sandbox Code Playgroud)
并依赖于 C++ 语义static来保证它只被调用一次而没有任何竞争条件。但是在纯 C 中做到这一点的最佳方法是什么?
这是我想出的:
pthread_once- 不确定它有什么开销,而且它可能会给 Windows 带来麻烦。fun_ptr为thread_local然后执行类似的操作 static thread_local fun_ptr_t fun_ptr = NULL;
if (!fun_ptr) {
fun_ptr = select_simd_function();
}
return (*fun_ptr)(str, len, ch);
Run Code Online (Sandbox Code Playgroud)
好处是代码非常清晰并且显然是正确的,但我不确定 TLS 的性能影响,而且每个线程都必须调用select_simd_function()一次(但这可能没什么大不了的)。
就我个人而言,到目前为止,(5) 是赢家,紧随其后的是 (1)(如果不是其他人非常基础的图书馆,我什至可能会选择 (1),而且我不想让自己难堪一个可能的错误实现)。
那么,最好的选择是什么?我错过了什么吗?
如果您可以使用 C11,这将起作用(假设您的实现支持线程 -这是一个可选功能):
#include <threads.h>
static fun_ptr_t fun_ptr = NULL;
static void init_fun_ptr( void )
{
fun_ptr = select_simd_function();
}
fun_ptr_t get_simd_function( void )
{
static once_flag flag = ONCE_FLAG_INIT;
call_once( &flag, init_fun_ptr);
return ( fun_ptr );
}
Run Code Online (Sandbox Code Playgroud)
当然,你提到了Windows。我怀疑 MSVC 是否支持这一点。
| 归档时间: |
|
| 查看次数: |
86 次 |
| 最近记录: |