c – 在同一线程上运行的所有OpenMP任务
我在OpenMP中使用任务编写了一个递归并行函数.虽然它给了我正确的答案并且运行良好但我认为并行性存在问题.与串行解决方案相比,运行时不会在我没有任务的情况下解决的同一个其他并行问题中扩展.当为每个线程打印任务时,它们都在线程0上运行.我正在Visual Studio Express 2013上编译并运行.
int parallelOMP(int n) { int a,b,sum = 0; int alpha = 0,beta = 0; for (int k = 1; k < n; k++) { a = n - (k*(3 * k - 1) / 2); b = n - (k*(3 * k + 1) / 2); if (a < 0 && b < 0) break; if (a < 0) alpha = 0; else if (p[a] != -1) alpha = p[a]; if (b < 0) beta = 0; else if (p[b] != -1) beta = p[b]; if (a > 0 && b > 0 && p[a] == -1 && p[b] == -1) { #pragma omp parallel { #pragma omp single { #pragma omp task shared(p),untied { cout << omp_get_thread_num(); p[a] = parallelOMP(a); } #pragma omp task shared(p),untied { cout << omp_get_thread_num(); p[b] = parallelOMP(b); } #pragma omp taskwait } } alpha = p[a]; beta = p[b]; } else if (a > 0 && p[a] == -1) { #pragma omp parallel { #pragma omp single { #pragma omp task shared(p),untied { cout << omp_get_thread_num(); p[a] = parallelOMP(a); } #pragma omp taskwait } } alpha = p[a]; } else if (b > 0 && p[b] == -1) { #pragma omp parallel { #pragma omp single { #pragma omp task shared(p),untied { cout << omp_get_thread_num(); p[b] = parallelOMP(b); } #pragma omp taskwait } } beta = p[b]; } if (k % 2 == 0) sum += -1 * (alpha + beta); else sum += alpha + beta; } if (sum > 0) return sum%m; else return (m + (sum % m)) % m; } 解决方法
实际问题:
您正在使用Visual Studio 2013. Visual Studio从未支持超过2.0的OMP版本(参见here). OMP任务是OMP 3.0的一项功能(参见spec). 因此,使用VS一定意味着没有OMP任务. 如果OMP任务是基本要求,请使用其他编译器.如果OMP不是必要条件,则应考虑使用备用并行任务处理库. Visual Studio包含MS并发运行时,以及基于它的Parallel Patterns Library.我最近从OMP转到了PPL,因为我正在使用VS工作;它不是一个简单的替代品,但它非常有能力. 我的第二次尝试解决这个问题,由于历史原因再次保留: 因此,几乎可以肯定的是,您在omp并行区域之外定义了omp任务. 这是一个人为的例子: void work() { #pragma omp parallel { #pragma omp single nowait for (int i = 0; i < 5; i++) { #pragma omp task untied { std::cout << "starting task " << i << " on thread " << omp_get_thread_num() << "n"; sleep(1); } } } } 如果省略并行声明,则作业将按顺序运行: starting task 0 on thread 0 starting task 1 on thread 0 starting task 2 on thread 0 starting task 3 on thread 0 starting task 4 on thread 0 但如果你把它留在: starting task starting task 3 on thread 1 starting task 0 on thread 3 2 on thread 0 starting task 1 on thread 2 starting task 4 on thread 2 成功,完全正确滥用共享输出资源. (作为参考,如果省略单个声明,每个线程将运行循环,导致在我的4 cpu VM上运行20个任务). 原始答案包括下面的完整性,但不再相关! 在每种情况下,你的omp任务都是一件简单的事情.它可能会立即运行并完成: #pragma omp task shared(p),untied cout << omp_get_thread_num(); #pragma omp task shared(p),untied cout << omp_get_thread_num(); 因为在开始下一个任务之前你永远不会启动一个长时间运行的任务,所以一切都可能在第一个分配的线程上运行. 也许你打算做这样的事情? if (a > 0 && b > 0 && p[a] == -1 && p[b] == -1) { #pragma omp task shared(p),untied { cout << omp_get_thread_num(); p[a] = parallelOMP(a); } #pragma omp task shared(p),untied { cout << omp_get_thread_num(); p[b] = parallelOMP(b); } #pragma omp taskwait alpha = p[a]; beta = p[b]; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |