线程中的任务 运行 比串行中的任务花费的时间更长?

tasks run in thread takes longer than in serial?

所以我在 400 万个节点上进行一些计算。

very bask 的串行版本只有一个 for 循环,它循环了 400 万次并进行了 400 万次计算。这大约需要 1.2 秒。

当我将 for 循环拆分为 4 个 for 循环并且每个循环执行 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;
}

没有声明的都是全局变量

The computation read from a shared array and write to a different shared array. I am sure they are not writing to the same byte.

在没有看到相关代码和更多细节的情况下无法确定,但这听起来可能是由于虚假共享,或者...

the performance issue of false sharing (aka cache line ping-ponging), where threads use different objects but those objects happen to be close enough in memory that they fall on the same cache line, and the cache system treats them as a single lump that is effectively protected by a hardware write lock that only one core can hold at a time. This causes real but invisible performance contention; whichever thread currently has exclusive ownership so that it can physically perform an update to the cache line will silently throttle other threads that are trying to use different (but, alas, nearby) data that sits on the same line.

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

更新

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

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

不要交错哪个核心处理哪些数据 i += ncores 给每个核心处理一个数据范围。

对我来说,在调试时 运行 也有同样的惊喜(尽管是其他测试代码)。

正在按预期全部发布 ;)