I have been trying to use a cilk_for loop in my Cilk++ code without data races. The first thing I tried is using reducer because I felt after reading the Cilk++ manual that reducer is better than lock in regards toperformance.
The problem I have is that I cannot get rid of data races by reducer (code is given below). Maybe I am not using the reducer right?
$ cat Rng.3.cilk
#include
#include
#include
cilk::reducer_opadd iWorker;void printThread()
{
iWorker.set_value( cilk::current_worker_id() );
std::cout << "Thread number is " << iWorker.get_value( ) << std::endl;
}int cilk_main()
{
cilk_for(int i = 0; i < 8; i++)
{
printThread();
}
return 0;
}$ ./Rng.3.exe
Thread number is 0
Thread number is 0
Thread number is 3
Thread number is 3
Thread number is Thread number is 3
1
Thread number is 7
Thread number is 2
This Cilk++ code above with reducer compiles fine, buthas data races which can be alsodetected by cilkscreen. Whereas the code below with lock does nothave data races which is verified bycilkscreen.
$ cat Rng.5.cilk
#include
#include
#includevoid printThread()
{
std::cout << "Thread number is " << cilk::current_worker_id() << std::endl;
}int cilk_main()
{
cilk::mutex mut;cilk_for(int i = 0; i < 8; i++)
{
mut.lock();
printThread();
mut.unlock();
}
return 0;
}$ ./Rng.5.exe
Thread number is 0
Thread number is 0
Thread number is 1
Thread number is 1
Thread number is 7
Thread number is 2
Thread number is 1
Thread number is 4
Question 1:Is there any way to fix my Cilk++ with reducer to avoid data races? How substantial is the difference in the performance between reducer and lock?
Question 2:I had an impression from that cilk::current_worker_id() does not actually represent thethread number. Is there something similar to omp_get_thread_num() in OpenMP? I am trying to eventually use Cilk++ to do the same task as the OpenMP code as below.
$ cat ranOpenMP.cpp
#include
#include "RngStream.h"
#include
using std::cout; using std::endl;
using std::cin;int main(){
int nP = omp_get_num_procs();
omp_set_num_threads(nP);unsigned long seed[6] ={1,2,3,4,5,6}; // initialial seed
RngStream::SetPackageSeed (seed); // initialize
RngStream RngArray[nP]; // create an array of objects// create the same number of random numbers as the number ofthreads
// using the method RandU01() in the class RngStreamfor(int i = 0; i < nP; i++)
{
cout << "For array element " << i << endl;
cout << "The random number is " << RngArray[i].RandU01() << endl;
}cout << "----------------------------------" << endl;
int myRank;
RngStream::SetPackageSeed (seed);
RngStream RngArrayNew[nP];// use OpenMP to create a parallel version so each thread creates a randomnumber
#pragma omp parallel for private(myRank)
for (int i = 0; i < nP; i++)
{
myRank = omp_get_thread_num(); // get the thread number
#pragma omp critical
{
cout << "For thread " << myRank << endl;
cout << "The random number is " << RngArrayNew[myRank].RandU01() << endl;
}
}return 0;
}$ g++ -c -fopenmp RngStream.cpp
$ g++ -c -fopenmp ranOpenMP.cpp$ g++ -fopenmp ranOpenMP.o RngStream.o -o rOMP
$ ./rOMP
For array element 0
The random number is 0.0010095
For array element 1
The random number is 0.701702
For array element 2
The random number is 0.476142
For array element 3
The random number is 0.0469012
For array element 4
The random number is 0.667972
For array element 5
The random number is 0.860096
For array element 6
The random number is 0.60096
For array element 7
The random number is 0.740441
----------------------------------
For thread 0
The random number is 0.0010095
For thread 3
The random number is 0.0469012
For thread 2
The random number is 0.476142
For thread 4
The random number is 0.667972
For thread 1
The random number is 0.701702
For thread 7
The random number is 0.740441
For thread 5
The random number is 0.860096
For thread 6
The random number is 0.60096
Thank you very much for your time and help.
Hailong



