C++ 在单独的缓存线上隔离非共享数据
我知道,作为提高应用程序性能的一般技术,建议设计一种结构,使非共享成员(跨线程)位于单独的缓存线上。这样就不会有C++ 在单独的缓存线上隔离非共享数据,c++,multithreading,caching,optimization,multicore,C++,Multithreading,Caching,Optimization,Multicore,我知道,作为提高应用程序性能的一般技术,建议设计一种结构,使非共享成员(跨线程)位于单独的缓存线上。这样就不会有错误共享,每个线程的内存访问效率也会更高 我想测试这是不是真的,所以我通过改变我的豚鼠结构做了下面的小测试 struct SharedSlow { int a_; int b_; int c_; int d_; }; struct SharedQuick { int a_ __attribute__((aligned(32))); int d_ __
错误共享
,每个线程的内存访问效率也会更高
我想测试这是不是真的,所以我通过改变我的豚鼠结构做了下面的小测试
struct SharedSlow {
int a_;
int b_;
int c_;
int d_;
};
struct SharedQuick {
int a_ __attribute__((aligned(32)));
int d_ __attribute__((aligned(32)));
int b_ __attribute__((aligned(32)));
int c_ __attribute__((aligned(32)));
};
将测试数据结构切换到“SharedQuick”后,线程“writer_b”将读取/写入成员b_和c_
,这些成员现在位于缓存线上,而a_和d_
是不同的(线程“writer_a”负责最后2个)
我得到的结果非常糟糕:与所有成员都在同一缓存线上的情况相比,性能最差
用时间测量
// Shared Slow
real 0m2.063s
user 0m4.102s
sys 0m0.001s
// Shared Quick
real 0m11.328s
user 0m22.420s
sys 0m0.002s
使用perf测量时
// Shared Slow
16k cycles
16 cache-misses
// Shared Quick
89k cycles
88 cache-misses
这两个线程位于单独的cpu上,因此它们应该非常独立地运行:
你知道性能恶化的原因是什么吗
我可以看到,与第一个数据结构相比,CPU所做的工作要多得多,但我不明白它们一直在忙什么,或者这些周期花在哪里:你有什么建议吗
#define NTIMES 100000
#define ARRSIZE 10000
void* writer_a(void* args)
{
cpu_set_t cpu;
CPU_ZERO(&cpu);
CPU_SET(0, &cpu);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu);
Shared* p = (Shared*)args;
for(int j=0;j<NTIMES; j++){
for(int i=0;i<ARRSIZE;i++){
p[i].a_ = j;
p[i].a_ += j;
p[i].d_ = p[i].a_;
p[i].d_ += j;
}
}
return 0;
}
void* writer_b(void* args)
{
cpu_set_t cpu;
CPU_ZERO(&cpu);
CPU_SET(15, &cpu);
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpu);
Shared* p = (Shared*)args;
for(int j=0;j<NTIMES; j++){
for(int i=0;i<ARRSIZE;i++){
p[i].b_ = j;
p[i].b_ += j;
p[i].c_ = p[i].b_;
p[i].c_ += j;
}
}
}
//typedef SharedSlow Shared;
typedef SharedQuick Shared; // this goes very slow
int main()
{
pthread_t first, second;
int ret = 0;
Shared* p = new Shared[ARRSIZE];
ret = pthread_create(&first,NULL, writer_a, p);
if(ret != 0){
cout << "err" << __LINE__ << endl;
exit(EXIT_FAILURE);
}
ret = pthread_create(&second,NULL, writer_b, p);
if(ret !=0){
cout << "err" << __LINE__ << endl;
exit(EXIT_FAILURE);
}
void *r1, *r2;
pthread_join(first, &r1);
pthread_join(second, &r2);
}
#定义次100000
#定义ARR大小10000
void*writer_a(void*args)
{
cpu\u设置\u t cpu;
CPU_零(&CPU);
CPU_设置(0,&CPU);
pthread_setaffinity_np(pthread_self(),sizeof(cpu_set_t),&cpu);
共享*p=(共享*)参数;
对于(int j=0;j@JoachimPileborgOP正在尝试测试错误共享。只有当两个不同的线程尝试访问同一缓存线(其中至少有一个是写线程)时才会发生这种情况。ARRSIZE有多大?它适合一级缓存吗?您好。这可能不是评估错误共享的正确测试。ARRSIZE是一个大数字每次从第一个线程循环到最后一个线程可能会导致缓存退出。两个线程不能完全同步到同一缓存线上,因此我相信它们只是独立地从内存中检索结构。两个缓存线分离意味着工作也会加倍(就像约阿希姆说的……他删除了响应吗?)对于CPU。@Mystical:我已经修复了代码,因为我遗漏了一段代码。ARRAYSIZE是10000