【问题标题】:How can I execute two for loops in parallel in C++?如何在 C++ 中并行执行两个 for 循环?
【发布时间】:2022-01-31 01:32:45
【问题描述】:

在 C++ 中,我希望同时执行两个 for 循环,而不是让一个等待另一个先执行或等待它结束。
我希望两个 for 循环(或更多)以相同的速度完成循环,这需要一个相同大小的循环才能完成。

我知道有人问过并回答过,但没有这么简单的例子。我希望能解决这个具体问题。我使用了 pragma omp 代码示例的组合,但无法获得结果。

#include <iostream>
using namespace std;

#define N 5

int main(void) { 
    int i;
    for (i = 0; i < N; i++) {
        cout << "This is line ONE \n";
    };

    #pragma omp parallel
    #pragma omp for             
    for (i = 0; i < N; i++) {
        cout << "This is line TWO \n";
    };
};

编译
$ g++ parallel.cpp -fopenmp &amp;&amp; ./a.out

代码的输出是这样的,在运行两个循环所花费的时间...

This is line ONE
This is line ONE
This is line ONE
This is line ONE
This is line ONE
This is line TWO
This is line TWO
This is line TWO
This is line TWO
This is line TWO  

我想要的输出是这样的 他们不必像这样一个接一个地打印,但我认为如果他们都同时进入循环的打印部分,他们会这样做。我真正需要的是循环同时开始和结束(循环相等)。

This is line ONE
This is line TWO
This is line ONE
This is line TWO
This is line ONE
This is line TWO
This is line ONE
This is line TWO
This is line ONE
This is line TWO

有这个问答here,但我不太明白未声明的foo//do stuff with item 部分。什么样的东西?什么项目?我无法从在线示例中推断出我需要做的事情。

【问题讨论】:

  • “我知道有人问过并回答过”在哪里?该答案中缺少哪一部分?为什么你的问题不同?
  • 这似乎是meta.stackexchange.com/questions/66377/what-is-the-xy-problem 即你想做一件很难的事情(X),因为你认为这会让做其他事情(Y)变得容易。尝试不同的方法。你为什么不想在一个循环中执行cout &lt;&lt; "This is line ONE \n"; cout &lt;&lt; "This is line TWO \n";,它会得到你想要的输出。
  • #pragma omp parallel 是否在已经完成的循环上向后工作?
  • 这是一个现实的示例代码吗? cout 在内部使用锁来防止任何数据竞争,因此它不能真正并行运行。同样的事情适用于printf(当然还有所有类似的功能)。您似乎不需要并行性,而是完全不同的 concurrency。您可以使用多个线程进行并发,但在现代硬件上以细粒度同步显然效率不高(除非两个线程在不同的硬件线程中在同一个内核中运行。OpenMP 似乎不是这里的好工具:它不提供并发功能(尽管它们可以被模拟)。
  • 您可以启动2个独立线程,一个循环读取传感器,另一个循环控制电机。

标签: c++ parallel-processing openmp


【解决方案1】:

正如 cmets 中已经提到的,OpenMP 可能不是这样做的最佳解决方案,但如果您希望使用 OpenMP 来实现,我建议如下:

使用sections启动2个线程,线程之间使用共享变量进行通信。重要的是使用原子操作来读取(#pragma omp atomic read seq_cst)和写入(#pragma omp atomic write seq_cst)这些变量。这是一个例子:

#pragma omp parallel num_threads(2)
#pragma omp sections
{                     
    #pragma omp section
    {
        //This is the sensor controlling part
            
        while(exit_condition)
        {
            sensor_state = read_sensor(); 
            
            // Read the currect state of motor from other thread
            #pragma omp atomic read seq_cst
            motor_state=shared_motor_state;
            
            // Based on the motor_state and sensor state send
            // a command to the other thread to control the motor
            // or wait for the motor to be ready in a loop, etc.
            
            #pragma omp atomic write seq_cst
            shared_motor_command= //whaterver you wish ;
        }
    }

    #pragma omp section
    {
        //This is the motor controlling part           
        while(exit_condition)
        {
            // read motor command form other thread
            #pragma omp atomic read seq_cst
            motor_command = shared_motor_command;

            // Do whatewer you have to to based on motor command and
            // You can set the state of motor by the following line

            #pragma omp atomic write seq_cst
            shared_motor_state= //what you need to pass to the other thread


        }
    }
}

【讨论】:

  • 谢谢。我正在安装库以尝试this。我会比较。
【解决方案2】:

我认为问题在于您不是尝试并行化两个循环,而是尝试并行化一个循环的工作。如果您将 std::cout &lt;&lt; "Hello from thread: " &lt;&lt; omp_get_thread_num() &lt;&lt; "\n"; 添加到您的第二个循环中,您会看到:

This is line TWO
Hello from thread: 0
This is line TWO
Hello from thread: 1
This is line TWO
Hello from thread: 2
This is line TWO
Hello from thread: 3
This is line TWO  
Hello from thread: 0

根据对线程的分配,四个线程是默认的线程数量(通常是内核数量),顺序可能会有所不同:例如 (0,1,2,3,0) 可能是 (0,2,3,1,0)

所以你要做的是第一个循环串行运行,然后(4 个或更多/更少)线程并行运行第二个循环。

问题是您是否真的想要使用 OpenMP 来并行化您的代码。如果是这样,您可以执行类似的操作:

#include <iostream>
#include <omp.h>
#include <String.h>


int main() {

    #pragma omp parallel for schedule(static)
    for(int i = 0; i < 10; i++){
        int tid = omp_get_thread_num();
        if (tid%2==0) {
            std::cout << "This is line ONE" << "\n";
        } else {
            std::cout << "This is line TWO" << "\n";
        }
    }
    return 0;
}

基于 threadID 的位置 - 如果是偶数线程,它将执行任务 1,如果是不均匀线程,它将执行任务 2。但是正如许多其他评论者所评论的那样,也许您应该考虑使用 p_threads,具体取决于在任务中。

【讨论】:

  • 它与电机和传感器一起运行了一点点。现在好了。然后我得到一个Segmentation fault (core dumped)。现在我觉得我应该在某处发布电机和传感器代码。作为记录,如果我不运行它,我不会在电机/传感器代码中出现错误。如果我注释掉所有传感器代码,电机工作得很好。这就是堵塞电机脉冲的原因。很抱歉,这与电机有关,并且 OP 中没有电机代码。
猜你喜欢
  • 2020-05-27
  • 1970-01-01
  • 2016-03-07
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 2013-05-02
  • 1970-01-01
  • 2013-09-13
相关资源
最近更新 更多