2010-12-22 34 views
3

我想了解来自here的openmp代码。你可以看到下面的代码。OpenMP程序中的低性能

  1. 为了测量串行和OMP的版本,我用time.h中,你找到正确的这种方法之间的加速比,差别?

  2. 程序在4核心机器上运行。我指定export OMP_NUM_THREADS="4",但看不到实质性的加速,通常我会得到1.2 - 1.7。在这种并行化中我面临哪些问题?

  3. 我可以使用哪种调试/执行工具来查看性能的损失?

代码(编译我用xlc_r -qsmp=omp omp_workshare1.c -o omp_workshare1.exe

#include <omp.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/time.h> 
#define CHUNKSIZE 1000000 
#define N  100000000 

int main (int argc, char *argv[]) 
{ 
    int nthreads, tid, i, chunk; 
    float a[N], b[N], c[N]; 
    unsigned long elapsed; 
    unsigned long elapsed_serial; 
    unsigned long elapsed_omp; 
    struct timeval start; 
    struct timeval stop; 


    chunk = CHUNKSIZE; 

    // ================= SERIAL  start ======================= 
    /* Some initializations */ 
    for (i=0; i < N; i++) 
     a[i] = b[i] = i * 1.0; 
    gettimeofday(&start,NULL); 
    for (i=0; i<N; i++) 
    { 
     c[i] = a[i] + b[i]; 
     //printf("Thread %d: c[%d]= %f\n",tid,i,c[i]); 
    } 
    gettimeofday(&stop,NULL); 
    elapsed = 1000000 * (stop.tv_sec - start.tv_sec); 
    elapsed += stop.tv_usec - start.tv_usec; 
    elapsed_serial = elapsed ; 
    printf (" \n Time SEQ= %lu microsecs\n", elapsed_serial); 
    // ================= SERIAL  end ======================= 


    // ================= OMP start ======================= 
    /* Some initializations */ 
    for (i=0; i < N; i++) 
     a[i] = b[i] = i * 1.0; 
    gettimeofday(&start,NULL); 
#pragma omp parallel shared(a,b,c,nthreads,chunk) private(i,tid) 
    { 
     tid = omp_get_thread_num(); 
     if (tid == 0) 
     { 
      nthreads = omp_get_num_threads(); 
      printf("Number of threads = %d\n", nthreads); 
     } 
     //printf("Thread %d starting...\n",tid); 

#pragma omp for schedule(static,chunk) 
     for (i=0; i<N; i++) 
     { 
      c[i] = a[i] + b[i]; 
      //printf("Thread %d: c[%d]= %f\n",tid,i,c[i]); 
     } 

    } /* end of parallel section */ 
    gettimeofday(&stop,NULL); 
    elapsed = 1000000 * (stop.tv_sec - start.tv_sec); 
    elapsed += stop.tv_usec - start.tv_usec; 
    elapsed_omp = elapsed ; 
    printf (" \n Time OMP= %lu microsecs\n", elapsed_omp); 
    // ================= OMP end ======================= 
    printf (" \n speedup= %f \n\n", ((float) elapsed_serial)/((float) elapsed_omp)) ; 

} 
+0

您可能还想指定哪个操作系统和哪个编译器来帮助其他人回答#1和#3。 – 2010-12-22 20:21:28

回答

1

有没有什么错误的代码上面,但你的加速是要通过这样的事实限制了主循环中,C = a + b很少工作 - 执行计算所需的时间(单个加法)将由存储器访问时间(2个加载和一个存储)占据主导地位,并且随着更多的线程操作在阵列上。

我们可以通过使循环内的工作测试这多个计算密集型:

c[i] = exp(sin(a[i])) + exp(cos(b[i])); 

然后我们得到

$ ./apb 

Time SEQ= 17678571 microsecs 
Number of threads = 4 

Time OMP= 4703485 microsecs 

speedup= 3.758611 

这显然是更接近了很多4倍加速比一个会期望。

更新:哦,还有其他问题 - gettimeofday()可能适用于定时,并且在您使用xlc的系统上 - 是AIX吗?在这种情况下,peekperf是一个很好的整体性能工具,硬件性能监视器可以让你访问存储器存取时间。在x86平台上,用于线程代码性能监视的免费工具包括用于高速缓存性能调试的cachegrind/valgrind(这里不是问题),用于常规OpenMP问题的scalasca,OpenSpeedShop也非常有用。