【发布时间】:2017-04-22 10:21:55
【问题描述】:
我有一个相当程序来展示 2 个类似程序的性能,它们都使用 2 个线程进行计算。核心区别在于一个使用全局变量,另一个使用“新”对象,如下所示:
#include<pthread.h>
#include<stdlib.h>
struct M{
long a;
long b;
}obj;
size_t count=2000000000;
void* addx(void*args){
long*pl=(long*)args;
for(size_t i=0;i<count;++i)
(*pl)*=i;
return NULL;
}
int main(int argc,char*argv[]){
pthread_t tid[2];
pthread_create(&tid[0],NULL,addx,&obj.a);
pthread_create(&tid[1],NULL,addx,&obj.b);
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
return 0;
}
clang++ test03_threads.cpp -o test03_threads -lpthread -O2 && time ./test03_threads
real 0m3.626s
user 0m6.595s
sys 0m0.009s
很慢,然后我修改了 obj 以动态创建(我希望它会更慢):
#include<pthread.h>
#include<stdlib.h>
struct M{
long a;
long b;
}*obj;//difference 1
size_t count=2000000000;
void* addx(void*args){
long*pl=(long*)args;
for(size_t i=0;i<count;++i)
(*pl)*=i;
return NULL;
}
int main(int argc,char*argv[]){
obj=new M;//difference 2
pthread_t tid[2];
pthread_create(&tid[0],NULL,addx,&obj->a);//difference 3
pthread_create(&tid[1],NULL,addx,&obj->b);//difference 4
pthread_join(tid[0],NULL);
pthread_join(tid[1],NULL);
delete obj;//difference 5
return 0;
}
clang++ test03_threads_new.cpp -o test03_threads_new -lpthread -O2 && time ./test03_threads_new
real 0m1.880s
user 0m3.745s
sys 0m0.007s
它比上一个快了惊人的 100%。我还在 linux 上尝试了 g++,结果相同。 但是这要怎么解释呢?我知道 obj 是全局变量,但 *obj 仍然是全局变量,只是动态创建的。核心区别是什么?
【问题讨论】:
-
可能与虚假共享有关,但人们会认为虚假共享在这两种实现中都是一个问题。
-
您的可执行文件是 32 位还是 64 位?
-
抱歉,什么是虚假分享?我在我的mac和linux上都测试过,结果稳定。
-
@Troskyvs :当 2 个线程处理位于同一缓存行中的对象时,一个线程的每次访问都会使另一个线程的缓存行无效,从而强制从更高的缓存/主缓存重新加载内存很贵。 (mechanical-sympathy.blogspot.be/2011/07/false-sharing.html)
标签: c++ linux performance variables pthreads