1

I have a C++ input that is formed as a std::vector and I would like to pass it to my OpenCL kernel (Nvidia platform).

But I keep getting a segmentation fault when the following is executed:

queue.enqueueReadBuffer(dev_input, CL_TRUE, 0, sizeof(bool) * input.size(), &input);

Therefore, I tried to copy my std::vector<bool> to a bool[] and everything worked perfectly. However, the common methods to convert a vector to a C array (&input[0], input.data()) don't work at all.

Would you have any suggestions either for the ReadBuffer or the fast assignment to a C array?

Thank you!

Yannis Assael
  • 1,099
  • 2
  • 20
  • 43
  • 2
    `vector` is "special". See e.g. http://stackoverflow.com/questions/670308/alternative-to-vectorbool?rq=1 – Jonathan Potter Mar 18 '15 at 06:53
  • How does your OpenCL kernel know the memory layout of your input? You're correctly using `sizeof(bool)` so your OpenCL kernel knows how many bytes of input there are, but it has no idea how many elements you pass. – MSalters Mar 18 '15 at 08:20
  • `sizeof(bool)` is 1 so its actually not needed but additionally I multiply with the `sizeof(bool) * input.size()`. Thank you for your help! – Yannis Assael Mar 18 '15 at 19:48

3 Answers3

6

Two problems.

  1. Implementations can (optionally) optimize std::vector<bool> to be more space efficient, perhaps by packing values into individual bits of memory. This will not match the layout of an array of bool.

  2. You can't pass the address of a vector as if it were an array.

    std::vector<bool> input;
    queue.enqueueReadBuffer(
        dev_input, CL_TRUE, 0,
        sizeof(bool) * input.size(), &input);
    //                               ^^^^^^ wrong
    

    If you want to pass a vector as a pointer, you have to either use input.data() or something like &input[0]. The reason these don't work is because std::vector<bool> is designed to prevent it, because the implementation might be optimized (see point #1).

This is basically a "wart" in the C++ library that has gotten baked in by time.

Fixing this is a pain.

// One way to do things...
struct Bool { bool value; }
std::vector<Bool> input;

// Another way to do things...
// (You have to choose the right type here, it depends
// on your platform)
std::vector<int> input;

// Yet another way...
bool *input = new bool[N];

That's why this is such a big stinking wart.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • Thank you for your reply! When I use either of `input.data()` or `&input[0]` I get a "invalid use of void expression" error. So, there is no way to use it directly? – Yannis Assael Mar 18 '15 at 07:02
  • 1
    Right. You will have to use some other data structure besides `std::vector`. I've expanded the answer. – Dietrich Epp Mar 18 '15 at 07:11
1

One possibility is to use the copy() algorithm provided by Boost.Compute.

Basically, you can do something like this:

// vector of bools on the host
std::vector<bool> host_vec = { ... };

// vector of bools on the device (each represented with a uchar)
boost::compute::vector<uchar_> gpu_vec(host_vec.size(), ctx);

// copy bool values on host to the device
boost::compute::copy(host_vec.begin(), host_vec.end(), gpu_vec.begin(), queue);

And Boost.Compute will take care of copying the data to the compute device correctly.

Kyle Lutz
  • 7,966
  • 2
  • 20
  • 23
1

One more thing to add:

Type bool within OpenCL kernel isn't guaranteed to match any of the host-side types. Generally, you should avoid using boolean types in Host-Device interconnection.

Roman Arzumanyan
  • 1,784
  • 10
  • 10