1

In C++ I would like two for loops to execute at the same time and not have one wait for the other one to go first or wait for it to end.
I would like the two for loops (or more) to finish the loops in the same speed it would take one loop of the same size to finish.

I know it's been asked and answered, but not in an example this simple. I'm hoping to solve this specific problem. I worked combinations of pragma omp code examples and couldn't get the result.

#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";
    };
};

Compiling
$ g++ parallel.cpp -fopenmp && ./a.out

The output of the code is this, in the time it takes to run two loops...

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  

The output I would like is this They don't have to print one after the other like this, but I would think they would if they were both getting to the print part of the loops at the same times. What I really need is for the loops to start and finish at the same time (with the loops being equal).

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

There's this Q&A here, but I don't quite understand the undeclared foo and the //do stuff with item parts. What kinda stuff? What item? I have not been able to extrapolate from examples online to make what I need happen.

Ant
  • 933
  • 2
  • 17
  • 33
  • 3
    "I know it's been asked and answered" Where? Which part is missing in that answer? Why is your question different? – Yunnosch Jan 30 '22 at 14:15
  • 3
    This seems to be a https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem I.e. you want to do one thing (X) which is hard, because you think it would make doing something else (Y) easy. Try a different approach. Why don't you want to do `cout << "This is line ONE \n"; cout << "This is line TWO \n";` in a single loop, it would get you exactly the desired output. – Yunnosch Jan 30 '22 at 14:17
  • The Qs and As that I saw were overly complex. I'm new to C++ and parallelism. If I ask for a smaller example I don't think it would be a blight on the website. If this question was asked and answered in a way I could understand I wouldn't have ten tabs open about how to do this. I don't mean to sound snarky. Text just sounds that way sometimes. I actually had this disclaimer in the question but I got a thumbs down, so I took out the disclaimer. Should I remove any allusion to duplication? – Ant Jan 30 '22 at 14:21
  • Discussing other explanations you found is actually very appreciated demonstration of your own research. However you need to do more than "I looked at lots, but all are too complicated for me to understand." Either discuss which part you did not understand or describe what you did understand, how far you got. What is the closest you got? – Yunnosch Jan 30 '22 at 14:24
  • The problem is that `#pragma omp parallel` doesn't do what I tried to get it to do. I know it's possible. "Why don't you want to do `cout << "This is line ONE \n"; cout << "This is line TWO \n";` in a single loop?" Because I need parallelism. I have a motor and a sensor I need to run in loops in parallel so one is not stifling the other. – Ant Jan 30 '22 at 14:24
  • If you need parallelism but you also need the output do be as perfectly in synch as you ask about here then I see a conflict. I could understand if you have a performance issue (meaning one CPU with much higher performance could also do the trick) and you only want to use the power of two cores. But you seem to be discussing real time design (what you describe) and in conflict with that ask for perfect synch in the shape of the desired output. Note, the problem might be me misunderstanding. But I recommend to give more explanation of why you think you need parallelism. – Yunnosch Jan 30 '22 at 14:28
  • Replacing the two output lines (basically a good approach to making a MRE, take that as a compliment) with some more detailed pseudo code might help. Something like "read out sensor; do time consuming calculation on sensor input; determine new target for motor position; move motor step by step towards target;". – Yunnosch Jan 30 '22 at 14:30
  • @Yunnosch I took code from [this page](https://tildesites.bowdoin.edu/~ltoma/teaching/cs3225-GIS/fall17/Lectures/openmp.html) and the ten other SO tabs I have open and tried modifying the code to see if I could get two loops to execute simultaneously. It would be a lot to cover all the combinations I worked. I need this parallelism because I have a motor and a sensor that I need processing independent of each other. Mostly because the motor needs to have very small, and specific pulses outputted to it. If it needs to wait to fetch readings from the sensor the motor gets out of whack. – Ant Jan 30 '22 at 14:33
  • @Yunnosch The motor and sensor both need their own loops anyway. I didn't want, or see the need to over complicate it with more details than the OP. – Ant Jan 30 '22 at 14:39
  • 1
    Does `#pragma omp parallel` work backwards on loops that have already finished? – QuentinUK Jan 30 '22 at 14:55
  • Obviously not. I did try it on the top loop only and both loops. I'm clueless. Sorry. It can't be a nested loop because I want the additional loop to start and end when the first one does. If it's nested it will loop n times as the first loop. – Ant Jan 30 '22 at 14:59
  • 3
    Is this a realistic example code? `cout` use a lock internally to prevent any data race so it cannot run truly in parallel. The same thing apply for `printf` (and certainly all similar functions). You appear not to need parallelism but *concurrency* which is totally different. You can do concurrency with multiple threads but synchronizing at fine grain is clearly not efficient on modern hardware (unless the two threads run in the same core in separate hardware threads. OpenMP appears not to be the good tool here: it does not provides concurrency features (although they can be emulated). – Jérôme Richard Jan 30 '22 at 15:43
  • 1
    You can start 2 independent threads, one looping to read the sensor and the other looping to control the motor. – Mark Setchell Jan 30 '22 at 15:48

2 Answers2

3

As already mentioned in the comments that OpenMP may not be the best solution to do so, but if you wish to do it with OpenMP, I suggest the following:

Use sections to start 2 threads, and communicate between the threads by using shared variables. The important thing is to use atomic operation to read (#pragma omp atomic read seq_cst) and to write (#pragma omp atomic write seq_cst) these variables. Here is an example:

#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


        }
    }
}
Laci
  • 2,738
  • 1
  • 13
  • 22
  • 1
    Thank you. I am in the process of installing the libraries to try [this](https://os.mbed.com/questions/48/Running-two-while-loop-in-parallel/). I will compare. – Ant Jan 30 '22 at 17:43
0

I think the issue is that you are not trying to parallelize two loops but instead you try to parallelize the work of one loop. If you would add std::cout << "Hello from thread: " << omp_get_thread_num() << "\n"; to your second loop you would see:

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

Depending on the assignment to threads, with four threads being the default amount of threads (often number of cores), the order might vary: example (0,1,2,3,0) could be (0,2,3,1,0)

So what you do is that the first loop is run in serial and then (4 or more/less) threads run the second loop in parallel.

The question is if you REALLY want to use OpenMP to parallelize your code. If so you could do something similar to:

#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;
}

Where based on the threadID - if it is an even thread it will do task 1, if it is an uneven thread it will do task 2. But as many other commenters have commented, maybe you should consider using p_threads depending on the task.

darclander
  • 1,526
  • 1
  • 13
  • 35
  • It runs for a little bit with the motor and sensor. Now well. Then I get a `Segmentation fault (core dumped)`. Now I feel like I should post the motor and sensor code somewhere. For the record, I don't get errors in the motor / sensor code if I run it without. The motor works great if I comment out all the sensor code. That's what clogs up the motors pulses. I'm sorry this became about motors and don't have the motor code in the OP. – Ant Jan 30 '22 at 19:30