Cannot assign to reducer_opor<bool>

Cannot assign to reducer_opor<bool>

I'd like to use a reducer to OR the bool results from a set of 4 Cilk threads, but icpc 12.1.0 will have none of that.

#include 
#include 
#include 
cilk::reducer_opor continueThis;
for (int i = 0; i < 2; i++) {
    for (int j = 0; j < 2; j++) {
        continueThis = cilk_spawn doStuff(i, j);
    }
}
cilk_sync;
bool continue = continueThis.get_value();

MyCode.cpp(766): error: no operator "=" matches these operands
            operand types are: cilk::reducer_opor = bool
              continueThis = cilk_spawn doStuff(i, j);
                                                     ^

The examples in the documentation use reducers of type , and imply that the assignment doesn't need a cast. Can a reduction variable not be the return value of a spawned function call?

5 post / 0 nuovi
Ultimo contenuto
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione

You are correct. Assignment is not supported for reducer_opor. However, you can use set_value():

#include 

int main(int argc, char **argv)
{
    cilk::reducer_opor mine(true);

    mine.set_value(true);

    if (mine.get_value())
        return 0;
    else
        return 1;
}

- Barry

The real problem that I had is assigning the return bool from a cilk_spawn to a reduction variable. Cilk just can't handle this, it seems. And if it does, I would still need separate code for the Cilk and non-Cilk versions. So to make things easier, I just implemented a reducer on my own.

    bool continueThis[4];

    for (int i = 0; i < 2; i++) {

        for (int j = 0; j < 2; j++) {

            continueThis[2*i+j] = cilk_spawn doStuff(i, j);

        }

    }

    cilk_sync;

    bool continue = false;

    for (int i = 0; i < 4; i++)

        continue |= continueThis[i];
This code works with or without Cilk, doesn't require ugly #ifdefs, and allows unsurprising initialization, if I so choose.

The limitation is on the reducer. If you added an assignment operator for reducer_opor, it should work.

Using a cilk_spawn in a loop is generally a bad idea. What you're saying is that the continuation of the loop hasto be stolen for everyiteration. In Cilk, spawns are(relatively) cheap. Steals are expensive. If your doStuff() routine doesn't do much, you're going to have a lot of overhead.

In contrast, cilk_foruses a hueristic to break the range into approximately 8*P "chunks" (P is the number of processors you've got). If your range is large, this means thateach chunk is a reasonable amount of work.

Itis tempting to recode your example as:

    bool continueThis[4];

    cilk_for (int i = 0; i < 2; i++) {

        cilk_for (int j = 0; j < 2; j++) {

            continueThis[2*i+j] = doStuff(i, j);

        }

    }

    cilk_sync;

    bool continue = false;

    for (int i = 0; i < 4; i++)

        continue |= continueThis[i];

But thiswill run into false-sharing issues. Each read/modify/write cycle willinvalidate the cacheline containing continueThis on all other CPUs, resulting in delays.

- Barry

Thanks for your continued help. The loops do actually only go to 2, and each doStuff can do a lot of work or a little---it's a recursive function over a sparse octree. Would this alternative be much different?

continueThis[0] = cilk_spawn doStuff(0,0);
continueThis[1] = cilk_spawn doStuff(0,1);
continueThis[2] = cilk_spawn doStuff(1,0);
continueThis[3] = cilk_spawn doStuff(1,1);
cilk_sync;
...
I'm not too worried about cache lines at this level---there is much more work in many of the subordinate functions.

Lascia un commento

Eseguire l'accesso per aggiungere un commento. Non siete membri? Iscriviti oggi