如何在没有 -fopenmp 标志的情况下启用 OpenMP?

0 c++ g++ intel openmp icc

在一些Online Judge平台上,代码的编译和运行方式如下:

g++ -O3 -std=c++17 a.cpp
./a.out
Run Code Online (Sandbox Code Playgroud)

我想使用 OpenMp 并行化我的代码,那么是否可以在没有 -fopenmp 标志的情况下启用 OpenMP?

#include <iostream>

using namespace std;

int main() {
#pragma omp parallel for
    for (int i = 0; i < 100; i++) {
        std::cout << i << std::endl;
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试将其添加到源代码中,但它不起作用:

#pragma GCC optimize("openmp")
Run Code Online (Sandbox Code Playgroud)

更新:上面的代码是一个糟糕的例子,这是另一个可以通过并行化加速的程序:

#include <iostream>
#include <cmath>
#include <chrono>

int main() {
    auto start = std::chrono::steady_clock::now();;
    double sum = 0;
    int n = 2e9;
    //std::cin >> n;
#pragma omp parallel for reduction(+:sum)
    for (int i = 0; i < n; i++) {
        sum += sqrt(i);
    }
    auto end = std::chrono::steady_clock::now();
    std::cout << sum << std::endl;
    std::cout << n << std::endl;
    std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

Ous*_*bel 6

为什么要并行化代码?在线法官问题应该按顺序解决。该问题的挑战在于降低运行时间复杂度。在线裁判不应该允许这种简单的理由违背竞争性节目的目的。

此外,如果您认为 N=100 时并行算法比顺序算法运行得更快,那么您就表现出了对并行化开销的极大无知。并行算法会带来巨大的同步成本,从而导致性能下降。

像这样的流 I/O 无法并行化;它必须按源顺序运行才能产生相同的输出。并且cout::operator<<是线程安全的,因此无论如何它都必须进行锁定以保护流缓冲区。

加快循环运行速度的一种方法是关闭 iostream 与 C stdio 缓冲区的同步,并且不要cout在每行之后刷新:

std::ios_base::sync_with_stdio(false);
for (int i = 0; i < 100; i++) {
    std::cout << i << '\n';
}
Run Code Online (Sandbox Code Playgroud)

还有一件事,std::endl相当于输出 a'\n并显式刷新流(进行系统调用)。在线判断程序大概会在输出重定向到文件或管道的情况下运行它,因此cout将是全缓冲的,不会在每个换行符上自动刷新。运行该程序的大部分成本(动态链接器启动除外)是执行 I/O 的系统调用,因此在每行上强制刷新可能会使速度慢 100 倍。

更快的方法可能是在缓冲区中准备一个长字符串,以避免cout每行锁定/解锁两次的开销,但这很小。通常,I/O 成本并不是竞争性编程的主要因素。