Search code examples
c++openclsycl

Is there a way I can create an array of cl::sycl::pipe?


I am using the Xilinx's triSYCL github implementation,https://github.com/triSYCL/triSYCL.

I am trying to create a design with 100 cl::sycl::pipes each with capacity= 6. And I am gonna access each pipe through a separate thread in my SYCL code.

Here is what I tried:

constexpr int T = 6;
constexpr int n_threads = 100;

cl::sycl::pipe<cl::sycl::pipe<float>> p { n_threads, cl::sycl::pipe<float> { T } };

for (int j=0; j<n_threads; j++) {
    q.submit([&](cl::sycl::handler &cgh) {
      // Get write access to the pipe
      auto kp = p[j].get_access<cl::sycl::access::mode::write>(cgh);
      // Get read access to the data
      auto ba = A.get_access<cl::sycl::access::mode::read>(cgh);

      cgh.single_task<class producer>([=] () mutable {
          for (int i = 0; i != T; i++)
            // Try to write to the pipe up to success
            while (!kp.write(ba[i]));
        });
};

The code is just a copy of tests/pipe/pipe_producer_consumer.cpp file on the github repository. I have just added a for loop on it to parallely instantiate multiple threads.

I am getting multiple errors in this: error: no matching function for call to ‘cl::sycl::pipe<cl::sycl::pipe<float> >::pipe(<brace-enclosed initializer list>)’ cl::sycl::pipe<cl::sycl::pipe<float>> p { n_threads, cl::sycl::pipe<float> { T } };


Solution

  • First, a disclaimer about the fact that cl::sycl::pipe are experimental things from the provisional SYCL 2.2 specification and that runs only on CPU (no accelerator, no FPGA...), and only in a very inefficient way.

    But of course it is useful to experiment about how a real design would work and how SYCL can work.

    A pipe is similar to some hardware FIFO.

    You wrote

    cl::sycl::pipe<cl::sycl::pipe<float>> p { n_threads, cl::sycl::pipe<float> { T } };
    

    which means a cl::sycl::pipe to transfer some... cl::sycl::pipe to transfer some float! While it would be nice to beam some hardware like in Star Trek, it is not possible yet in the current version of SYCL to send real hardware through pipes. :-)

    Probably a code like yours could work, but with a real array of pipes. But the issue is that pipes need some size specified at construction time...

    A few ideas I could think of would be std::vector<cl::sycl::pipe<float>> p and a loop doing n_threads p.emplace_back(T).

    Or you could use some metaprogramming (Boost.Hana might help...) to construct a std::array<cl::sycl::pipe<float>> from an initializer list of n_threads T.

    Or you could use an intermediate object with a default construction doing the pipe you are interested in.

    struct my_pipe : cl::sycl::pipe<float> {
      my_pipe() : pipe { T } {};
    };
    
    std::array<my_pipe, n_threads> p;
    

    That said, I have not tried...

    Furthermore, after thinking at it, I do not really see why in SYCL 2.2 the pipes could not have default constructors since they are just a wrappers around the OpenCL equivalent objects. I will push this to the SYCL committee. Thank you for making SYCL better. :-)

    If all this makes sense, please post the final working code and make a pull-request on https://github.com/triSYCL/triSYCL with a new unit test code. :-)

    If you are looking at some examples of metaprogramming with SYCL, look at https://www.khronos.org/assets/uploads/developers/library/2017-supercomputing/Xilinx-triSYCL-complete_Nov17.pdf slides 45--49 https://www.youtube.com/watch?v=4r6FXxknJEA