OpenMP:共享同一算法的单线程和多线程实现

时间:2019-08-29 04:40:04

标签: c++ multithreading openmp

我正在一个代码库中工作,其中两次实现了几种算法:一次在正确的位置使用$(document).on('mousemove', function (e) { dragMove(e) }) var dragMove = function (e) { if (oldPageY > e.pageY) { limit = true } if (dragging) { // console.log(oldPageY, e.pageY) if (oldPageX < e.pageX) { xDirection = 'next drag' if (limit) { $(fsTrack).addClass('fs-being-dragged') // disable items from being clicked nextItem(dragItemsToMove) limit = false } oldPageX = e.pageX - pageXOffset } else { xDirection = 'prev drag' if (limit) { $(fsTrack).addClass('fs-being-dragged') // disable items from being clicked prevItem(dragItemsToMove) limit = false } oldPageX = e.pageX + pageXOffset } return false } } ,一次不使用。这些函数被命名为#pragma omp parallelAlgorithmMT()之类的东西。

简化示例:

AlgorithmST()

假设我需要保留两个单独的功能(不能更改更高级别的代码),并且应该允许用户在运行时在它们之间进行选择,那么我如何才能使这两个功能共享一个共同的实现?

我意识到该算法有点荒谬,可以在循环内无需/// Multi-threaded algorithm std::vector<double> AlgorithmMT(int n) { std::vector<double> result(n); std::itoa(result.begin(), result.end(), 1.0); #pragma omp parallel for for (int i = 0; i < n; ++i) { result[i] = i / result[i]; } return result; } /// Single-threaded algorithm std::vector<double> AlgorithmST(int n) { std::vector<double> result(n); std::itoa(result.begin(), result.end(), 1.0); // NOTE: there is no #pragma here for (int i = 0; i < n; ++i) { result[i] = i / result[i]; } return result; } 读取依赖的情况下实现。请仅假设这是算法的必需结构。 :)

3 个答案:

答案 0 :(得分:4)

一种干净的方法是使用if构造的parallel子句,例如:

bool is_parallel = ...;
#pragma omp parallel for if (is_parallel)

这是在运行时进行评估的,并且按定义具有产生单个线程的相同效果。

此运行时区别与省略pragma并不完全相同,编译器可能会不同地优化代码。虽然我不会太担心,但是您应该观察一下自己的表现。只需编译不带-fopenmp的应用程序,然后将性能与动态禁用的并行性进行比较。 如果存在差异,则可能必须求助于冗余代码或以某种方式帮助编译器。请注意,性能可能因编译器而异。

答案 1 :(得分:1)

您可以使用OpenMP运行时API中的omp_set_num_threads将线程数限制为并行部分之前的一,然后在该部分之后将其恢复。

警告::如果已经有其他并行线程在运行,那么omp_set_num_threads也将影响那里的并行部分。

答案 2 :(得分:0)

由于name city state.abbreviation 是预处理程序,因此您不能做太多可悲的事情。 您可以使用内部函数创建#pragma,但用algorithm.cpp.part代替%parallel%,然后在编译时,在makefile中用以下内容替换文本:

#pragma omp for

如果您有很多这样的功能,那么使用良好的makefile规则可以很好地扩展。

或者,如果您正在为Windows进行编译,则可以使用并发运行时,这样可以避免使用sed '/%parallel%/c\#pragma omp parallel' algorithm.cpp.part > algorithm_mt.cpp sed '/%parallel%/c\ ' algorithm.cpp.part > algorithm_st.cpp ,这在您遇到的情况中会很有用。

(这个答案不要太苛刻,我是在手机上写的)