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

Posted

技术标签:

【中文标题】OpenMP:共享同一算法的单线程和多线程实现【英文标题】:OpenMP: Share single-threaded and multi-threaded implementations of the same algorithm 【发布时间】:2019-08-29 04:40:04 【问题描述】:

我在一个代码库中工作,其中几个算法被实现了两次:一次在正确的位置使用#pragma omp parallel,一次没有。这些函数被命名为AlgorithmMT()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;

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

我意识到该算法有点荒谬,并且可以在没有读取依赖于循环内的result 的情况下实现。请假设这是算法所需的结构。 :)

【问题讨论】:

【参考方案1】:

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

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

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

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

【讨论】:

这看起来很棒。我试试看!【参考方案2】:

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

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

【讨论】:

【参考方案3】:

因为#pragma 是预处理器,所以你不能做很多事情。 你可以用你的函数创建algorithm.cpp.part,但用%parallel%代替#pragma omp for,然后在编译时,在makefile中用类似这样的东西替换文本:

sed '/%parallel%/c\#pragma omp parallel'  algorithm.cpp.part > algorithm_mt.cpp
sed '/%parallel%/c\ '  algorithm.cpp.part > algorithm_st.cpp

如果你有很多这样的函数,它可以通过良好的 makefile 规则进行相对较好的扩展。

或者,如果您正在为 Windows 编译,您可以使用并发运行时,它会避免使用 #pragma,这在您的情况下可能很有用。

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

【讨论】:

您可以在运行时更改最大线程数,有效地使代码单线程。 但如果多个线程需要不同的设置,可能会导致问题。无论如何,我们的两个答案都是 hack,真的可能导致更大的问题。

以上是关于OpenMP:共享同一算法的单线程和多线程实现的主要内容,如果未能解决你的问题,请参考以下文章

多线程与多进程的比较

实验二:多线程

多个 OpenMP 线程读取(不写入)共享变量的性能成本?

多线程控制讲解与代码实现

什么是多线程,多进程?

[国嵌攻略][087][多线程程序设计]