为什么并行版本比单线程版本慢.虚假分享



所以这里有两个版本的代码:

class VectorCount {
private:
char               *arr;int                
size;unsigned long long count;
public:
VectorCount(char *arr, unsigned int size, unsigned long long count) : arr(arr), size(size), count(count) {}
void add() {
while(count--) {
for (int i = 0; i < size; i++) {
arr[i]++;
}
}
}
};
// Single-thread version of the code
void main_st() {
// initizalize array
char arr[10];
// create object
VectorCount v(arr, 10, 100000000);
// run add
v.add();
}
// Parallelized version of the code
void main_mt() {
// initialize array
char arrA[10];
char arrB[10];
// create objects
VectorCount v1(arrA, 10, 50000000);
VectorCount v2(arrB, 10, 50000000);
// create threads
thread t1, t2;
t1.create_thread(v1, v1.add);
t2.create_thread(v2, v2.add);
// join threads
t1.join();
t2.join();
// Code to do the final sum of the two VectorCount objects to get the same
// result as the single-threaded version (assume negligible overhead here)
}

假设程序创建VectorCount对象的单个实例,数组大小为10,计数为1亿。单线程版本需要5秒才能完成总和。并行版本使用两个线程,每个线程都拥有一个单独的VectorCount实例,数组大小为10,因此每个VectorCount实例的计数仅为5000万,因为每个线程完成了一半的工作。并行版本需要8秒才能完成。为什么速度较慢?我以为这是由于虚假的分享。但我不确定。缓存大小为64字节。

我们能让并行版本运行得更快吗?我正在考虑更改VectorCount数组大小。但是,使用2个线程,多大的大小才能使并行版本运行得更快?由于缓存大小是64字节,int是4字节,那么在这种情况下,size=16会解决错误共享吗?(4 x 16=64(。

谢谢你的帮助。

您的代码几乎不起作用,只要有足够的上下文,优化器基本上就可以将代码转换为(假设count可被size整除(:

for (int i = 0; i < size; i++) {
arr[i] = count / size;
}

由于arr的值从未使用过,优化器甚至可以消除此代码。

请注意,由于arr未初始化,您的代码具有未定义的行为。您应该使用char arr[10] {0}将数组初始化为0

然而,优化者的工作越复杂,就越不可能发现这些机会。通过std::thread构造函数的机制传递数组和参数可能会阻止优化器意识到它可以通过这种方式优化代码。将代码重新排列为:

std::thread t1([] {
char arrA[10]{0};
VectorCount v1(arrA, 10, 50'000'000);
v1.add();
});
std::thread t2([] {
char arrA[10]{0};
VectorCount v1(arrA, 10, 50'000'000);
v1.add();
}
);

使其更类似于单线程版本,优化器能够发挥其魔力,并行版本更快:https://godbolt.org/z/9j9ocoMTd.如果你查看第一个版本的程序集代码,你会注意到提到了50000000,但没有提到100000000,在第二个版本中,你会发现50000000也不存在,因为两个版本都优化到了零。

请注意,它仍然比单线程版本慢,但由于单线程版本只需要大约100ns,创建和连接2个线程的开销可能比并行节省的开销更多。

在我的visual studio机器上,单线程版本的代码需要85毫秒,并行版本需要45毫秒(visual studio无法完全删除您的代码(。

阻止优化器会在GCC上得到更相似的结果:https://godbolt.org/z/Mhf5xjx33

相关内容

最新更新