2014-11-14 70 views
0

我正在學習OpenMP的過程。這是一個循環,我使用這是for循環有效使用OpenMP

std::string result; 
#pragma omp parallel 
    { 
     #pragma omp parallel for public(local_arg) reduction(+:result) 
     for(int i=0 ; i<Myvector.size();i++) 
     { 
      result = result + someMethod(urn,Myvector[i]); 
     } 
    } 

現在someMethod(urn,Myvector[i])將在上面的代碼中調用多個線程將返回一個字符串。該字符串需要附加到返回字符串。我的問題是我需要鎖定for循環中的語句嗎?有更好的方法嗎?有什麼建議麼 ?

+0

是的,您需要在這種方式的結果周圍放置一個關鍵部分。我會在答案中寫出一個備選方案。 – defube

+0

感謝您的期待。我還寫了一些使用簡化的els。不知道這是否有助於 – MistyD

+0

哪個編譯器?可能你可以使用編譯器的併發/並行庫。 – Ajay

回答

0

這並不完美(自從我使用OpenMP以來已經有一段時間了),但這個想法是基本的分而治之。

std::vector<std::string> results; 

int n = 2*omp_get_num_threads(); 
results.reserve(n); // For reliability, ask OS about # of cores, double that. 

// Reserve a small string for each prospective worker 
for(int i = 0; i < n; ++i){ 
    std::string str{}; 
    str.reserve(worker_reserve); 
    results.push_back(move(str)); 
} 

// Let each worker grab and mutate the string 
// corresponding to its worker ID 
// 
#pragma omp parallel for 
for(int i = 0; i < Myvector.size(); ++i) 
{ 
    auto &str = results[omp_get_thread_num()]; 

    str.append(someMethod(urn, Myvector[i])); 
} 

// Measure the total size of the result 
std::string end_result; 
size_t total_len = 0; 
for(auto &res : results){ 
    total_len += res.length(); 
} 

// Reserve and combine 
end_result.reserve(total_len + 1); 

for(auto &res : results){ 
    end_result.append(res); 
} 

但是,仍然存在堆爭用的問題。

另外omp_get_num_threads不保證返回實際的線程數。

+0

另外,如何獲得線程數的最大值,以便在可能對我可用的循環中工作 – MistyD

+0

這不可預測。 OpenMP使用系統線程池,並且策略通常「儘可能多」。我想我可能需要稍微調整一下答案... – defube

+0

你能否那樣做。另外你爲什麼要做'results.reserve(threadcount)'?線程數可以少於vector的內容。我相信它應該是'results.reserve(Myvector.size())' – MistyD