在线程中运行的任务比在序列中运行的时间更长?

时间:2015-10-30 15:17:42

标签: c parallel-processing pthreads

所以我在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;
}

未声明的所有内容都是全局变量

1 个答案:

答案 0 :(得分:2)

  

计算从共享数组读取并写入不同的共享数组。我确信他们没有写到同一个字节。

如果没有看到相关代码并获得更多细节,就无法确定,但这听起来可能是因为错误的共享,或者......

  

虚假共享(又称缓存行ping-ponging)的性能问题,其中线程使用不同的对象,但这些对象恰好在内存中足够接近它们落在同一缓存行上,并且缓存系统将它们视为单个块由硬件写锁有效保护,一次只能有一个核可以保存。这会导致真实但无形的性能争用;无论哪个线程当前拥有独占所有权,以便它可以物理地执行对缓存行的更新,将默默地限制尝试使用位于同一行的不同(但是,附近)数据的其他线程。

http://www.drdobbs.com/parallel/eliminate-false-sharing/217500206

<强>更新

这看起来很可能会触发错误共享,具体取决于向量的大小(尽管帖子中仍然没有足够的信息可以确定,因为我们没有看到各种vector分配。

for(i = index; i < node_size ; i+=ncores) 

而不是交错哪个核心可以处理哪些数据i += ncores为每个数据提供了一系列数据。