2014-10-08 27 views
0

我正在求解2D離散域(LX,LY)上的4個等式。這4個eqns需要解決1000個時間步驟。每個公式將需要(i,j)位置處的參數a,b和c。 我在main()中動態地創建了a_m,b_m和c_m,我將它們的地址傳遞給每個線程。多個pthreads被多次調用;比串行代碼慢

我創建了4個函數eq1,eq2,eq3,eq4。

我爲每個公式創建LX * LY線程數。 每個線程ID將重新表示域LX,LY中的唯一(i,j)。 因此,每個線程只能在向量a_m,b_m,c_m中的特定數據位置(i,j)上工作。 然後,我在main()中依次調用4個eqn。 這4個方程應該按照bcoz的順序求解,參數a,b和c在每個方程(i,j)上被更新。

我的程序運行速度比串行計算慢。你能否提出一些優化技巧來加快速度。

我想創建4個線程,每個方程一個,並解決每個線程的LX * LY時間不會提供太多的加速。

# define N LX*LY 
struct thread_data 
{ 
    int thread_id, t; 
    double *a, *b, *c ; 
}; 

struct thread_data thread_data_array[N]; 


//Function declaration 

void *eqn1(void *threadarg) 
{ 
//implementation of eqn1 
    pthread_exit(NULL); 
    return 0; 
} 

void *eqn2(void *threadarg) 
{ 
//implementation of eqn2 

    pthread_exit(NULL); 
    return 0; 
} 

void *eqn3(void *threadarg) 
{ 
//implementation of eqn3 
    pthread_barrier_wait (&barrier); 
    pthread_exit(NULL); 
    return 0; 
} 

void *eqn4(void *threadarg) 
{ 
//implementation of eqn4 
    pthread_exit(NULL); 
    return 0; 
} 

//所有的主要

void * main(void *) 
{ 
    pthread_t threadid[N]; 
//dynamically create a_m, b_m and c_m of size N each 
    for(time=0; time<10000; time++) 
    { 

     for(i=0; i<N; i++) 
     { 
     //thread_data_array[i] is initialized 
     // *a,*b,*c in thread_data_array[i] will save address of a_m,b_m,c_m created dynamically in main() 
     pthread_create(threadid[i], eq1, (void *) &thread_data_array[i]); 
     } 

     for(i=0; i<N; i++) 
     { 
     //thread_data_array[i] is initialized 
     // *a,*b,*c in thread_data_array[i] will save address of a_m,b_m,c_m created dynamically in main() 
     pthread_create(threadid[i], eq2, (void *) &thread_data_array[i]); 
     } 

     for(i=0; i<N; i++) 
     { 
     //thread_data_array[i] is initialized 
     // *a,*b,*c in thread_data_array[i] will save address of a_m,b_m,c_m created dynamically in main() 
     pthread_create(threadid[i], eq3, (void *) &thread_data_array[i]); 
     } 

     for(i=0; i<N; i++) 
     { 
     //thread_data_array[i] is initialized 
     // *a,*b,*c in thread_data_array[i] will save address of a_m,b_m,c_m created dynamically in main() 
     pthread_create(threadid[i], eq4, (void *) &thread_data_array[i]); 
     } 

     for(j=0;j<N; j++) { 
     pthread_join(threadid[j], NULL); 
     } 

    } 

free(a_m); free(b_m); free(c_m); 

} 
+0

你知道每個連續的for循環都會破壞等待來自先前循環的剛剛啓動的,現在孤立的線程的任何機會,對吧?即只有最後一組是等待的,並且毫無疑問與所有這些孤兒線直接競爭。 pthread_create的第一個參數是錯誤的,它應該是'threadid + i',而不是'threadid [i]',並且你的編譯器應該告訴你這一點。如果這沒有錯,我會驚訝。上面的 – WhozCraig 2014-10-08 18:23:09

+0

是一個僞代碼,語法不準確。你是對的,它應該是&threadid [i]。 – user2415927 2014-10-08 18:52:12

+0

發佈代碼並不代表你正在做的事。我們無法讀懂你的想法。我們所能讀到的只是你發佈的代碼和單詞。 – 2014-10-08 18:57:19

回答

0

首先,代碼中有一些錯誤。您的eq2,eq3,eq4循環將隔離之前創建的線程。我認爲你的代碼有未定義的行爲。如果您修復了代碼,那麼您可以繼續進行優化。

一個大問題是線程創建開銷。你基本上創建並銷燬線程1000次。如果與eq1,eq2 ...相關的代碼很簡單,那麼由線程創建/銷燬產生的開銷很高。

如果您不是被迫使用pthread,我會選擇OpenMP。

如果你想使用並行線程,你可能需要實現一個「線程池」

如果你去OpenMP的,你會做這樣的事情:

for(time=0; time<10000; time++) 
    { 
     #pragma omp parallel for 
     for(i=0; i<N; i++) 
     { 
     eq1(&thread_data_array[i]); 
     eq2(&thread_data_array[i]); 
     eq3(&thread_data_array[i]); 
     eq4(&thread_data_array[i]); 
     } 
    } 

和OpenMP運行時就知道了根據您的機器啓動多少個線程。

+0

我正在用pthread做這個練習,以便在MPI和多線程之間進行速度比較。我無法將MPI與多線程結合起來進行此練習。 – user2415927 2014-10-08 18:49:51

+0

OpenMP不是MPI。 OpenMP在同一進程內創建多個線程。 MPI只是創建更多的流程。因此,如果您將MPI與OpenMP進行比較,就像比較MPI和MultiThreading一樣。 – VAndrei 2014-10-08 18:58:16

0

這是簡單使一個多線程應用程序比單線程應用程序運行速度慢。

您甚至可以使用pthread功能使單線程應用程序運行得相當慢。例如,考慮一個由循環組成的函數,循環的主體增加一個全局計數器。您必須保護該增量以使此功能在多線程應用程序中可用。例如,夾在互斥鎖和解鎖之間的增量。當只有一個線程時,這個線程安全版本比基本版本運行速度慢得多。添加另一個線程和繁榮!性能大幅降低。

雖然你不應該這樣做,上面顯示出

  • 有一點開銷參與線程。

  • 爭用率很高時,存在大量的開銷和浪費。你希望代碼在解鎖和鎖之間做一些事情。使幾乎所有關鍵因素都破壞了多線程的目的。

我提到了互斥體,因爲你忽略了一堆代碼(沒有顯示)。如果你在這個被刪除的代碼中有很多鎖定和解鎖操作,那可能是你問題的一部分。

使多線程應用程序性能比串行性差的另一種方式是壓倒你的機器。一個經驗法則是,你不應該有超過M個使用CPU的活動線程,其中M是你機器上有效CPU的數量。除非您在刀片服務器上運行您的代碼,否則這個M是個小數字。如果您有多於M個嘗試使用CPU的活動線程,則會造成很多爭用。你的4 * N很可能比這個M多很多。

你不能只在線程後線程產生線程,並期望性能提高。這是降低性能的好方法。如果您想要使用粗粒度並行性(例如,線程)並行運行大量計算,最好使用線程池。線程池限制活動線程的數量。 POSIX線程不提供線程池功能。您必須自行推出或在互聯網上找到適合您需求的產品。

還有一種方法可以使多線程應用程序執行比串行更糟的是不加入完成的線程。你正在用你的代碼創建許多不可連接的線程。即使它們已經完成,您仍然有問題,因爲那些已完成但未合併的線程代表增加爭用的資源。如果它們沒有完成,你就會壓倒你的機器。