huseyin tugrul buyukisik
huseyin tugrul buyukisik

Reputation: 11920

C++: how can I use parallel-for macro multiple times in same scope?

I'm using a local function definition to run a code block N times acting like a parallel-for version of C# but it gives multiple definition error for f function when I use two or more of it in same scope. How can I make the function name incrementally changed such as f1,f2,f3,.. after each usage in same scope?


Definition:

#ifndef PARALLEL_FOR
#define PARALLEL_FOR(N,O) \
                        struct LocalClass                                                           \
                        {                                                                           \
                            void operator()(int i) const O                                      \
                        } f;                                                                        \
                        std::thread threads[N];                                                     \
                        for(int loopCounterI=0; loopCounterI<N; loopCounterI++)                     \
                        {                                                                           \
                            threads[loopCounterI]=std::thread(f,loopCounterI);                      \
                        }                                                                           \
                        for(int loopCounterI=0; loopCounterI<N; loopCounterI++)                     \
                        {                                                                           \
                            threads[loopCounterI].join();                                           \
                        }                                                                           \

#endif

Usage:

PARALLEL_FOR(
        5,
        {std::cout<<100*i<<std::endl;}
);

output:

0
300
200
100
400

normally adding {\ and }\ would solve for consequent calls but what if I do nested parallel for?

Upvotes: 0

Views: 447

Answers (2)

O&#39;Neil
O&#39;Neil

Reputation: 3849

Instead of passing a unique ID, you could use __LINE__.

But instead of an ugly macro, why don't you use a function with a lambda?

template <int N, class F>
void parallel_for(F f) {
    std::thread threads[N]; // or std::array<std::thread, N> threads;

    for(int loopCounterI=0; loopCounterI<N; loopCounterI++) {
        threads[loopCounterI]=std::thread(f,loopCounterI);
    }
    for(int loopCounterI=0; loopCounterI<N; loopCounterI++) {
        threads[loopCounterI].join();
    }
}

Used like this:

parallel_for<5>([] (int i) {
    std::cout<<100*i<<std::endl;
});

The lambda can capture the variables you need:

int j = ...;
parallel_for<5>([j] (int i) {
    std::cout<<100*(i+j)<<std::endl;
});

Upvotes: 5

Daniel
Daniel

Reputation: 651

Although it doesn't seem like the ideal solution to me, you can concatenate strings in macros using ##. In your code do the following

#ifndef PARALLEL_FOR
#define PARALLEL_FOR(N,O,usageInd) \
                    struct LocalClass##usageInd                                                           \
                    {                                                                           \
                        void operator()(int i) const O                                      \
                    } f##usageInd;                                                                        \
                    std::thread threads[N];                                                     \
                    for(int loopCounterI=0; loopCounterI<N; loopCounterI++)                     \
                    {                                                                           \
                        threads[loopCounterI]=std::thread(f##usageInd,loopCounterI);                      \
                    }                                                                           \
                    for(int loopCounterI=0; loopCounterI<N; loopCounterI++)                     \
                    {                                                                           \
                        threads[loopCounterI].join();                                           \
                    }                                                                           \

#endif

It would be up to you to now pass an index for each usage.

Upvotes: 2

Related Questions