所以我在400万个节点上进行一些计算。
非常bask的串行版本只有一个for循环,它循环400万次并进行400万次计算。这大概需要1.2秒。
当我将for循环拆分为4循环并且每次执行1/4计算时,总时间变为1.9秒。
我想在创建for循环时会有一些开销,可能与cpu喜欢在块中计算数据有关。
真正困扰我的是当我尝试在8核机器上将4个循环放到4个线程时,每个线程需要0.9秒才能完成。 我期待他们每个人只需要花费1.9 / 4秒。
我不认为有任何竞争条件或同步问题因为我所做的就是有一个for循环来创建4个线程,这需要200微秒。然后是一个for循环来加入它们。
计算从共享数组读取并写入不同的共享数组。 我确信他们没有写到同一个字节。
开销可以从哪里来?
main:ncores:核心数量。 node_size:图形的大小(400万个节点)
for(i = 0 ; i < ncores ; i++){
int *t = (int*)malloc(sizeof(int));
*t = i;
int iret = pthread_create( &thread[i], NULL, calculate_rank_p, (void*)(t));
}
for (i = 0; i < ncores; i++)
{
pthread_join(thread[i], NULL);
}
calculate_rank_p:vector是页面排名计算的排名向量
Void *calculate_rank_pthread(void *argument) {
int index = *(int*)argument;
for(i = index; i < node_size ; i+=ncores)
current_vector[i] = calc_r(i, vector);
return NULL;
}
calc_r:这只是使用压缩行格式的页面排名计算。
double calc_r(int i, double *vector){
double prank = 0;
int j;
for(j = row_ptr[i]; j < row_ptr[i+1]; j++){
prank += vector[col_ind[j]] * val[j];
}
return prank;
}
未声明的所有内容都是全局变量
答案 0 :(得分:2)
计算从共享数组读取并写入不同的共享数组。我确信他们没有写到同一个字节。
如果没有看到相关代码并获得更多细节,就无法确定,但这听起来可能是因为错误的共享,或者......
虚假共享(又称缓存行ping-ponging)的性能问题,其中线程使用不同的对象,但这些对象恰好在内存中足够接近它们落在同一缓存行上,并且缓存系统将它们视为单个块由硬件写锁有效保护,一次只能有一个核可以保存。这会导致真实但无形的性能争用;无论哪个线程当前拥有独占所有权,以便它可以物理地执行对缓存行的更新,将默默地限制尝试使用位于同一行的不同(但是,附近)数据的其他线程。
http://www.drdobbs.com/parallel/eliminate-false-sharing/217500206
<强>更新强>
这看起来很可能会触发错误共享,具体取决于向量的大小(尽管帖子中仍然没有足够的信息可以确定,因为我们没有看到各种vector
分配。
for(i = index; i < node_size ; i+=ncores)
而不是交错哪个核心可以处理哪些数据i += ncores
为每个数据提供了一系列数据。