2015-03-25 55 views
0

我想將OpenMP並行化添加到工作代碼中(僅適用於單個for循環),但是我無法擺脫分段錯誤。該問題起因於這一行:OpenMP Segfault

pos += sprintf(com + pos, "%d ", i); 

com是一個字符陣列,我試圖將其定義爲char com[255]char *com = malloc(255*sizeof(char)),內部和for循環之前。當我在循環之前定義com時,我添加了private(com)#pragma omp parallel for指令。我也嘗試初始化它,並使用firstprivate。 (pos是一個整數,初始化爲0

當我不加-fopenmp一切工作正常,但-fopenmp它給段錯誤。我錯過了什麼?

+0

更多的代碼在解決你的問題時相當有幫助 – dvhh 2015-03-25 04:57:59

+0

最有可能的是,你也必須使'''pos'''專用 – Ulterior 2015-03-25 04:59:44

回答

4

段故障來自多個線程同時更新的pos值,因此將其設置爲某個值,輪流com + pos成指向超出或com所分配的存儲器之前的指針。到parallelise這樣一個循環的正確方法是串聯在私人字符串值,然後串聯私人字符串有序方式:

char com[255]; 
int pos = 0; 

#pragma omp parallel 
{ 
    char mycom[255]; 
    int mypos = 0; 

    #pragma omp for schedule(static) nowait 
    for (int i = 0; i < N; i++) 
     mypos += sprintf(mycom + mypos, "%d ", i); 

    // Concatenate the strings in an ordered fashion 
    #pragma omp for schedule(static) ordered 
    for (int i = 0; i < omp_get_num_threads(); i++) 
    { 
     #pragma omp ordered 
     pos += sprintf(com + pos, "%s", mycom); 
    } 
} 

ordered結構可確保正確的同步,以便一個不需要critical。使用schedule(static)對於確保每個線程處理迭代空間的單個連續部分非常重要。

+0

這是一個聰明的解決方案。如果有一種方法可以獲得塊大小,並根據塊大小(我可以做到這一點,但它不是優雅的)而不是所有的'N'來分配'mypos',這樣就不會浪費內存。我的意思是'mypos'的大小可以大致爲'N/nthreads'。顯然,這個例子沒有什麼區別。 – 2015-03-25 12:50:56

+0

嗯,我只是因爲懶惰而將'mypos'的大小設置爲255,因此模擬'private(com)'。由於時間表是「靜態的」,並且線程的數量是已知的,所以可以容易地計算它(種類)。 – 2015-03-25 16:03:42

+0

我認爲這是我第一次看到'ordered'實際上是有用的:在並行填充私有數據時,按順序合併它們。這樣可以避免保存每個線程的私有數據,並將它們在並行區域外部串行合併。根據你的回答,我更新了我的答案[這裏](https://stackoverflow.com/questions/18669296/c-openmp-parallel-for-loop-alternatives-to-stdvector/18671256#18671256)。謝謝!我想知道這是否可以用戶定義的減少? – 2015-03-26 08:58:22