[英]openmp: recursive task slower than sequential even with depth limit
我有一棵很大的二叉樹,我想在上面進行某些昂貴的計算。 我想使用openmp及其任務編譯指示來並行化這些方法。
作為測試,我並行化了freeTree
函數,並創建了一個很大的示例測試樹。 為了防止產生許多任務,我將任務創建限制在樹的前兩個級別。 因此,實際上僅創建了4個任務。
下面是最小的工作示例:
#include <chrono>
#include <iostream>
class Node {
public:
int data;
Node* l;
Node* r;
Node(Node* left, Node* right) : l(left), r(right) {}
};
Node* createRandomTree(int depth) {
if (depth == 0)
return new Node(NULL, NULL);
return new Node(createRandomTree(depth - 1), createRandomTree(depth - 1));
}
void freeTree(Node* tree) {
if (tree == NULL) return;
freeTree(tree->l);
freeTree(tree->r);
delete tree;
}
void freeTreePar(Node* tree, int n = 0) {
if (tree == NULL) return;
Node *l = tree->l, *r = tree->r;
if (n < 2) {
#pragma omp task
freeTreePar(l, n + 1);
#pragma omp task
freeTreePar(r, n + 1);
} else {
freeTree(tree->l);
freeTree(tree->r);
}
// taskwait is not necessary
delete tree;
}
int main(int argc, char const *argv[])
{
std::chrono::time_point<std::chrono::system_clock> start, end;
Node* tree = createRandomTree(22);
start = std::chrono::system_clock::now();
#pragma omp parallel shared(tree)
{
#pragma omp single nowait
freeTreePar(tree);
}
end = std::chrono::system_clock::now();
std::chrono::duration<double> elapsed_seconds = end-start;
std::time_t end_time = std::chrono::system_clock::to_time_t(end);
std::cout << "finished computation at " << std::ctime(&end_time)
<< "elapsed time: " << elapsed_seconds.count() << "s\n";
return 0;
}
當我運行此代碼時,大約需要0.38秒才能釋放樹。 但是,如果我直接調用freeTree(root)
,則只需0.2秒。 因此,即使樹很大(2 ^ 22個元素),並且即使在此特定測試用例中任務的大小相等,使用並行方法也無法提高性能。
難道我做錯了什么? 您知道我如何改進此代碼嗎? 謝謝!
有些任務實際上不能並行化,因為某些資源一次只能由一個線程訪問(線程安全)。 這就是動態內存的情況。
現在,malloc / free基本上是線程安全的。
=>將對每個malloc / free執行一次鎖定。
因此,您不能輕松地改進這種代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.