2011-10-03 64 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加速。

相關問題