2011-10-03 61 views
0

我正在研究openMP中的代码。代码必须在文件中打印2到1000000之间的所有素数。串行算法需要150秒来完成所有计算,其中两个线程export OMP_NUM_THREADS=2代码在81秒内运行(意味着加速等于1.85)。但多达2 export OMP_THREADS=3,4线程,加速不会改变。它仍然等于〜1.8。如何在我的代码中使线程加速超过3个线程?

我也改变了调度没有任何改变。

我的代码在哪里primes.cpp。你可以过去,在你的编辑器复制并与以下行编译命令:

~$ g++ primes.cpp -o primes -fopenmp

变化过程中,以2(不管你喜欢或)数量

~$ export OMP_NUM_THREADS=2

变化任务调度(静态,动态,制导)

~$ export OMP_SCHEDULE=dynamic,100000

~$ ./primes

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <vector> 
#include <algorithm> 
#include <time.h> 
#include <omp.h> 

#define SIZE 1000000 

using namespace std; 



int main(){ 
    // code permettant derecuperer dans un fichier la liste des 
    // nombres premiers entre O et SIZE 

    // variables 
    int cprime; 
    int chunk; 
    int lap, loop, i; 
    int isprime; 
    int count; 

    FILE * file; 
    char * filename; 

    time_t t1; 
    vector<int>primelist; 

    int thread_num; 
    //omp_sched_t schedule; 

    // initialisation 
    t1 = time(NULL); 
    chunk = 100000; 
    count = 0; 

    filename = (char *) malloc(sizeof(char)*100); 
    strcpy(filename, "primes.txt"); 

    file = fopen(filename, "w"); 

    // ------------- ALGORITHME --------------- 
    #pragma omp parallel private(thread_num) 
    { 
     thread_num = omp_get_thread_num(); 

     if(thread_num == 0) 
      printf("%d processor are available for work\n", omp_get_num_threads());  

     #pragma omp barrier 
     #pragma omp critical 
     { 
    printf("I'm processor %d ready for work\n", thread_num); 
     } 

    } 

    #pragma omp parallel for private(cprime, loop, isprime) schedule(runtime)  shared(primelist) reduction(+:count) 
    for(cprime = 2; cprime < SIZE; cprime++){ 

     loop = 1; 
     isprime = 1; 

     // looking if it's a prime number 
     while((++loop<cprime) && isprime){ 
      if(cprime % loop == 0) isprime = 0; 
     } 

     if(isprime) {  
      #pragma omp critical 
      { 
      primelist.push_back(loop); 
      } 

      count++; 
     } 

     #pragma omp critical 
     { 
      if(cprime % chunk == 0) 
      printf("Indicator from thread %d current(size N) : %d\n",omp_get_thread_num(),  cprime); 
     } 

    } 

    sort(primelist.begin(), primelist.end()); 
    lap = primelist.size(); 

    for(i = 0; i < lap; i++) 
     fprintf(file, "%d\n", primelist[i]); 

    fclose(file); 

    printf("%d primes where discover between 0 and %d, duration of the operation   %d\n", count, SIZE, (int) difftime(time(NULL), t1)); 

    return 0; 

} 

运行环境信息运行

我的电脑有4个处理器

我已经验证它在那里说明从processor : 0转到文件/proc/cpuinfoprocessor 3。都是英特尔(R)酷睿(TM)i5的CPU中号600 @ 2.53GHz的

感谢您的任何答复

回答

2

检查你正在运行它的计算机上的CPU。如果它没有超过2个内核,那么除了两个线程之外,你不可能看到太多的改进。

请注意考虑超线程CPU,它们的核心数量是操作系统真实核心数量的两倍。

1

我做的第一件事盲人在

http://www.vi-hps.org/datapool/page/18/fuerlinger.pdf

使用一个OpenMP的探查等,以便弄清楚,如果事情是错的并行性。这可能是你正在认真对抗事情中的推波助澜,这需要时间。或者也许for循环没有被正确的并行化,尽管快速浏览并没有告诉我它本身有什么错误。

接下来,记住按照已知最快的串行实现来测量您的代码。 Knuth中有一个,TaOCP基于hard筛选,以并行算法击败。

1

首先你不应该期望从一个微不足道的实现中获得线性加速。只有极少数情况下,并行实现可以线性扩展任意数量的内核。

但是,您的代码和测量运行时的方式也存在一些问题。两者都可能会给你一个加速不好的印象。

关于你的代码我必须说,同步(在你的情况下有一个关键部分)总是显着减慢你的软件。我自己已经有好几次这个问题了。但与你的问题相反,我事先知道我的矢量中有多少元素。所以我可以先调整矢量大小并将元素放在正确的位置,而不将它们附加到矢量中。这显着加速了许多处理器的代码。不过,我没有针对您的问题的类似解决方案。

您的代码中还存在一些小错误:您的变量count在几次分配后不会有任何可预测的值。它也应该在关键部分(或者您可以使用atomic操作)。更好的方法是使这个变量的OpenMP private在for循环和使用还原+,像这样:

#pragma omp parallel for private(cprime, loop, isprime, count) reduction (+: count) schedule(runtime) 

这完成了循环后会产生正确的结果为count

我不是很明白你为什么在for中使用schedule(runtime)或者在这里实际发生了什么。但是您应该知道,您将覆盖您之前使用export声明设置的时间表。

现在,下面是定时应用程序的问题:您正在计时整个应用程序,而不仅仅是并行for循环。在这种情况下,你应该考虑你还包括一个顺序排序。这限制了您可以从应用程序中获得的加速。而且,对于顺序应用程序的初始基准测试,您应该只使用一个线程来打开OpenMP;它将比没有OpenMP的应用程序慢,因为OpenMP - 即使只有一个线程 - 也会有小的开销。这可能会给你两个线程的预期2x加速。

相关问题