cilk

How to use cilk_reducer variable to write data into a file without race condition(#opencilk)


#opencilk Am using opencilk open source parallel lib to do parallel task. In that we have hyperobject called reducer to elimate data race and also we have cilk_reducer datatype. How to use this cilk_reducer variable to write data into a file without data race

How to write void identity(void *view) and void reduce(void *left,void *right) function So that i can write data into a file without data race


Solution

  • I can imagine a couple simple solutions to your question, depending on what exactly you are trying to do.

    Option 1: You can create a standard linked-list reducer to store everything to be written to the file. Once the program has accumulated everything to be written to the file into that linked list, it can iterate through the linked list and write all of its elements to the file. Overall, this is probably the simplest option.

    Option 2: If you're writing C++-based Cilk code, then you can use the ostream reducer distributed with OpenCilk. Here is an example of how to use that reducer:

    #include <fstream>
    #include <cilk/cilk.h>
    #include <cilk/ostream_reducer.h>
    
    // Create a standard output file stream.
    std::ofstream outf;
    // Create an ostream_reducer that uses the output file stream.
    cilk::ostream_reducer<char> output(outf);
    
    void print_numbers_to_file(int n) {
      // Open the file stream.
      outf.open("file.out");
    
      // Write to the ostream_reducer in parallel.
      cilk_for(int i = 0; i < n; ++i) {
        output << i << "\n";
      }
    
      // Close the file stream.
      outf.close();
    }
    

    At a high level, the ostream reducer works by keeping track of different kinds of views. Internally, this reducer uses a view type that refers to either a file stream or a private string buffer. The initial view, created when the reducer is defined, refers to the specified file stream, which is outf in the above example. All other views are constructed automatically by calling the identity function. For the ostream reducer, identity constructs a new view that contains a private string buffer, which is used to store in memory anything written to that view.

    The ostream reducer's reduce function behaves differently depending on the pair of views it is run on. If both views have private string buffers, then reduce writes the contents of one view's string buffer into the other. If one view refers to the file stream, then the other view must refer to a private string buffer. In that case, reduce writes the contents of the private string buffer to the file stream.

    You can create your own cilk_reducer variable in C that behaves like the ostream reducer, but that takes a bit of work. I suspect you would find the linked-list option to be simpler.