在C ++ OpenMP中以两种方式使用蒙特卡罗方法计算pi

时间:2015-11-24 10:03:18

标签: c++ algorithm openmp montecarlo

哪种方法应该更快? 第一种方法是增加一个变量用于减少:

#pragma omp parallel private(seed, x, y, i) reduction (+:counter)
{
    seed = 25234 + 17 * omp_get_thread_num();
    nproc = omp_get_thread_num();
    #pragma omp parallel for
    for(i=0; i<prec/8; i++){
        x = (double)rand_r(&seed) / RAND_MAX;
                y = (double)rand_r(&seed) / RAND_MAX;
        if(x*x+y*y<1){
            counter++;
        } 

}

第二个是每个进程使用增量变量表,最后,该表中元素的总和是结果:

#pragma omp parallel private(seed, x, y, i , nproc)
{
    seed = 25234 + 17 * omp_get_thread_num();
    nproc = omp_get_thread_num();
    #pragma omp parallel for
    for(i=0; i<prec/8; i++){
        x = (double)rand_r(&seed) / RAND_MAX;
        y = (double)rand_r(&seed) / RAND_MAX;
        if(x*x+y*y<1){
            counter[nproc]++;
        } 

    }
}

double time = omp_get_wtime() - start_time;
int sum=0;
for(int i=0; i<8; i++){
    sum+=counter[i];

} 

理论上,第二种方式应该更快,因为进程不共享一个变量,但每个进程都有自己的变量。 但是当我计算执行时间时:

first approach: 3.72423 [s]

second approach: 8.94479[s]

我认为错了或我在代码中做错了什么?

1 个答案:

答案 0 :(得分:4)

在第二种方法中,您是false sharing的受害者。这是一个有趣的article from Intel

  

当不同处理器上的线程修改时,会发生错误共享   驻留在同一缓存行上的变量。这使得无效   缓存行并强制执行内存更新以保持缓存一致性。

     

如果两个处理器在同一存储器中对独立数据进行操作   地址区域可存储在单行中,缓存一致性   系统中的机制可能会迫使整条线路穿过公交车或   与每次数据写入互连,另外还会导致内存停顿   浪费系统带宽

直观地说,我不认为第一种方法应该更慢 您确实在每个线程上创建了一个私有副本,然后将最终结果应用于全局变量。行为在某种程度上与您的共享阵列相同,但这里的问题是即使您的访问是独立的,您也会得到错误的共享。