gpt4 book ai didi

c - 线程本地存储开销

转载 作者:太空狗 更新时间:2023-10-29 17:19:24 24 4
gpt4 key购买 nike

假设有一些使用全局变量的不可重入函数:


int i;
void foo(void){
/* modify i */
}

然后,我想在多线程代码中使用这个函数,所以我可以这样更改代码:


void foo(int i){
/* modify i */
}

或者,通过使用 gcc __thread 说明符,更简单:


__thread int i;
void foo(void){
/* modify i */
}

最后一个的优点是我不需要更改另一个调用 foo() 的代码。

我的问题是,线程本地存储的开销是多少? TLS 是否存在一些不明显的问题?

如果我通过单独的指针修改 TLS`ed 变量,是否会有一些开销,如下所示:


__thread int i;
void foo(void){
int *p = &i;
/* modify i using p pointer */
}

谢谢。

最佳答案

And then, I want to use this function in multithreaded code, so I can change code this way:

void foo(int i){
/* modify i */
}

这肯定有效,因为您只会修改i 的副本。如果您希望保留更改,则需要传递 int*int&

与您为实现相同功能而可能遵循的任何自定义方法相比,使用 TLS 肯定不会造成任何重大开销(无论是空间还是时间)。在实践中,编译器通过在全局数据结构中动态分配存储“槽”来实现 TLS,该数据结构包含您的线程局部变量。

当您在运行时访问线程局部变量时,有一个额外的间接级别:首先运行时必须为当前线程访问适当的线程局部变量表,然后从表中获取值.此提取是使用数组的索引完成的(这是一个 O(1) 操作)。

如果您打算这样做:

__thread int i;
void foo(void){
int *p = &i;
/* modify i using p pointer */
}

那么就不需要使用指针访问i。将 i 视为一个全局变量,它对每个正在运行的线程都有不同的值。您不需要通过指针访问普通全局变量来使更改保持不变,因此也不需要将指针与线程局部变量一起使用。

最后,线程本地存储并不是真的要为每个线程存储大量变量(TLS 表的大小有依赖于编译器的限制)但这是您可以轻松解决的问题:将许多变量放入一个 struct 并创建一个指向 struct 线程局部的指针。

关于c - 线程本地存储开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5450694/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com