2011-10-06 93 views
0

我想在特定的代碼片段上使用OpenMP。不確定片段是否需要修改,可能是爲了順序執行而設置過於嚴格。反正這裏是我想要並行化(僞)代碼:並行for循環的C++ OpenMP指令?

#pragma omp parallel for private(id, local_info, current_local_cell_id, local_subdomain_size) shared(cells, current_global_cell_id, global_id) 
for(id = 0; id < grid_size; ++id) { 
    local_info = cells.get_local_subdomain_info(id); 
    local_subdomain_size = local_info.size(); 
    ...do other stuff... 
    do { 
     current_local_cell_id = cells.get_subdomain_cell_id(id); 
     global_id.set(id, current_global_cell_id + current_local_cell_id); 
    } while(id < local_subdomain_size && ++id); 
    current_global_cell_id += local_subdomain_size; 
} 

這使得完整意義上的連續感(盯着它一段時間後),這也可能意味着它需要重新編寫爲OpenMP。我關心的是current_local_cell_id和local_subdomain_size是私有的,但是current_global_cell_id和global_id是共享的。

因此,聲明current_global_cell_id + = local_subdomain_size內部循環後:

do { 
    ... 
} while(...) 
current_global_cell_id += local_subdomain_size; 

可能導致了OpenMP設置錯誤,我懷疑。如果任何OpenMP專家能夠提供有關我可以用來對代碼進行最小更改的特殊OMP指令的某些指針,但仍然可以利用OpenMP來處理這種for循環,我將不勝感激。

回答

2

我不知道我理解你的代碼。不過,我認爲你真的想要一些並行的積累。

你可以使用一個像模式

size_t total = 0; 
#pragma omp parallel for shared(total) reduction (+:total) 
for (int i=0; i<MAXITEMS; i++) 
{ 
     total += getvalue(i); // TODO replace with your logic 
} 

// total has been 'magically' combined by OMP 

在相關的註釋,當你使用gcc,你可以只使用__gnu_parallel::accumulate簡易替換爲std::accumulate,這確實exactly相同。見Chapter 18. Parallel Mode

size_t total = __gnu_parallel::accumulate(c.begin(), c.end(), 0, &myvalue_accum); 

你甚至可以-D_GLIBCXX_PARALLEL這將使所有使用std算法,如果可能的話自動parallellized編譯。 除非你知道你在做什麼,否則不要使用它!通常情況下,性能會受到影響,並且由於意外的並行性而引入錯誤的機會是真實的

+0

在GNU並行模式上添加提示 – sehe

+0

有趣的評論。感謝您分享此信息。 –

1

更改循環內的id不正確。沒有辦法將環路分派給不同的線程,因爲循環步驟不會產生可預測的標識值。

爲什麼你在使用while循環中的id?

+0

感嘆!你可能是對的。我希望避免改變這一點。但我認爲,如果我將current_global_cell_id也設爲私人,它可能仍然有效,不是嗎? –

+0

這不是真正的全球性;然而那個變量用於什麼?它不會工作,直到id在循環中沒有改變 – crazyjul