如何使用OpenMP正确并行处理for循环?

时间:2018-09-04 01:34:09

标签: c++ for-loop parallel-processing openmp

我正在测试OpenMP for C ++,因为我的软件将严重依赖处理器并行化的速度。

运行以下代码时,我得到奇怪的结果。

  • 并行化的速度没有我预期的那么快
  • 不使用-O标志时,代码运行 slower

我正在i5-8600 CPU和16 GB RAM上使用g ++编译器7.3.0版和Ubuntu 18.04 OS。

输出:

Output 1 (Not allowed to embed yet since I'm a new member)

Transript:

.../OpenMPTest$ g++ -O3 -o openmp main.cpp -fopenmp
.../OpenMPTest$ ./openmp
6 processors used.
Linear action took: 2.87415 seconds.
Parallel action took: 0.99954 seconds.

Output 2

.../OpenMPTest$ g++ -o openmp main.cpp -fopenmp
.../OpenMPTest$ ./openmp
6 processors used.
Linear action took: 25.7037 seconds.
Parallel action took: 68.0485 seconds.

如您所见,对于6个处理器,除非忽略-O标志,否则我的速度只会提高2.9倍,在这种情况下,程序运行速度要慢得多,但仍会以100%的利用率使用所有6个处理器(使用htop测试)。

这是为什么?另外,我该怎么做才能将性能提高6倍?

源代码:

#include <iostream>
#include <ctime>
#include <ratio>
#include <chrono>
#include <array>
#include <omp.h>

int main() {

    using namespace std::chrono;

    const int big_number = 1000000000;
    std::array<double, 6> array = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };

    // Sequential

    high_resolution_clock::time_point start_linear = high_resolution_clock::now();

    for(int i = 0; i < 6; i++) {
        for(int j = 0; j < big_number; j++) {
            array[i]++;
        }   
    }

    high_resolution_clock::time_point end_linear = high_resolution_clock::now();

    // Parallel 

    high_resolution_clock::time_point start_parallel = high_resolution_clock::now();

    array = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};

    #pragma omp parallel
    {
        #pragma omp for
        for(int i = 0; i < 6; i++) {
            for(int j = 0; j < big_number; j++) {
                array[i]++;
            }   
        }
    }

    high_resolution_clock::time_point end_parallel = high_resolution_clock::now();

    // Stats.

    std::cout << omp_get_num_procs() << " processors used." << std::endl << std::endl;

    duration<double> time_span = duration_cast<duration<double>>(end_linear - start_linear);
    std::cout << "Linear action took: " << time_span.count() << " seconds." << std::endl << std::endl;

    time_span = duration_cast<duration<double>>(end_parallel - start_parallel);
    std::cout << "Parallel action took: " << time_span.count() << " seconds." << std::endl << std::endl;

    return EXIT_SUCCESS;
}

1 个答案:

答案 0 :(得分:1)

似乎您的代码受false sharing的影响。

不要让不同的线程访问同一条缓存行。一种更好的方法是尝试不要在线程之间共享变量。

O(N*lgN*lgN)

使用了8个处理器。

进行线性动作:26.9021秒。

并行动作耗时:6.41319秒。

您可以阅读this