KhronosGroup/SyclParallelSTL

Cannot access copied lambda vectors

Closed this issue · 2 comments

I am having problems with the following bit of code, namely the two locations where in is accessed within the algorithm call:

void f(std::vector<float> &out, std::vector<float> in, uint2 outSize) {

    std::vector<uint> pixels(outSize.x*outSize.y);
    std::iota(pixels.begin(), pixels.end(), 0);

    std::experimental::parallel::transform(half_sample_par, pixels.begin(), pixels.end(), out.begin(), [=](uint pos) {
        uint x = pos % outSize.x;
        uint y = pos / outSize.x;

        const float center = in[centerPixel.x + centerPixel.y*inSize.x];

        std::vector<int2> pairs = generate_int_pairs(-r+1, r, -r+1, r);
        std::for_each(pairs.begin(), pairs.end(), [&](int2 p) {
            ...
            float current = in[cur.x + cur.y*inSize.x];
            ...
        });

        return t/sum;
    });
}

I get the error below during compile time. I understand that in is essentially a vector of pointers and that the reference copied by the lambda cannot be used to access memory. Is there any easy workaround for this? For all the algorithm is concerned, in is a static variable used only for reading in values.

Using two input iterators for std::transform is not an option as in is indexed at different locations in the function. I am fairly sure zipping the in values along with pixels will not help much.

[ 71%] Building ComputeCpp integration header file /home/dom/gu/Project/slambench/build/kfusion/track.cpp.sycl
/home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:33:30: error: [Computecpp:CC0011]: cannot capture object in of type 'std::vector<float>' in a SYCL kernel, because it contains a field with a
      pointer type
        const float center = in[centerPixel.x + centerPixel.y*inSize.x];
                             ^
/home/dom/computecpp-ce-0.5.1/include/SYCL/apis.h:1299:5: note: in instantiation of function template specialization 'cl::sycl::kernelgen_parallel_for_nd<(anonymous namespace)::half_sample, (lambda
      at /home/dom/sycl_parallel_stl/include/sycl/algorithm/transform.hpp:71:14)>' requested here
    kernelgen_parallel_for_nd<
    ^
/home/dom/sycl_parallel_stl/include/sycl/algorithm/transform.hpp:70:9: note: in instantiation of function template specialization 'cl::sycl::handler::parallel_for<(anonymous namespace)::half_sample,
      (lambda at /home/dom/sycl_parallel_stl/include/sycl/algorithm/transform.hpp:71:14), 1>' requested here
      h.parallel_for<typename ExecutionPolicy::kernelName>(
        ^
/home/dom/sycl_parallel_stl/include/sycl/execution_policy:202:18: note: in instantiation of function template specialization 'sycl::impl::transform<sycl::sycl_execution_policy<(anonymous
      namespace)::half_sample>, __gnu_cxx::__normal_iterator<unsigned int *, std::vector<unsigned int, std::allocator<unsigned int> > >, __gnu_cxx::__normal_iterator<float *, std::vector<float,
      std::allocator<float> > >, (lambda at /home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:23:104)>' requested here
    return impl::transform(named_sep, b, e, out_b, op);
                 ^
/home/dom/sycl_parallel_stl/include/experimental/algorithm:132:14: note: in instantiation of function template specialization 'sycl::sycl_execution_policy<(anonymous
      namespace)::half_sample>::transform<__gnu_cxx::__normal_iterator<unsigned int *, std::vector<unsigned int, std::allocator<unsigned int> > >, __gnu_cxx::__normal_iterator<float *,
      std::vector<float, std::allocator<float> > >, (lambda at /home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:23:104)>' requested here
  return sep.transform(b, e, out, op);
             ^
/home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:23:34: note: in instantiation of function template specialization
      'std::experimental::parallel::transform<sycl::sycl_execution_policy<(anonymous namespace)::half_sample> &, __gnu_cxx::__normal_iterator<unsigned int *, std::vector<unsigned int,
      std::allocator<unsigned int> > >, __gnu_cxx::__normal_iterator<float *, std::vector<float, std::allocator<float> > >, (lambda at
      /home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:23:104)>' requested here
    std::experimental::parallel::transform(half_sample_par, pixels.begin(), pixels.end(), out.begin(), [=](uint pos) {
                                 ^
/home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:12:9: note: captured object defined here
        std::vector<float> in,
        ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_vector.h:216:20: note: std::vector derives from std::_Vector_base
    class vector : protected _Vector_base<_Tp, _Alloc>
                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_vector.h:166:20: note: std::_Vector_base contains field std::_Vector_base<float, std::allocator<float> >::_M_impl of
      type 'struct std::_Vector_base<float, class std::allocator<float> >::_Vector_impl'
      _Vector_impl _M_impl;
      ~~~~~~~~~~~~~^~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/stl_vector.h:84:2: note: offending field std::_Vector_base<float, std::allocator<float> >::_Vector_impl::_M_start of
      type 'pointer' defined here
        pointer _M_start;
        ^
In file included from /home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:1:
In file included from /home/dom/gu/Project/slambench/kfusion/./include/kernels_stl.h:5:
In file included from /home/dom/gu/Project/slambench/kfusion/./include/commons.h:35:
In file included from /home/dom/gu/Project/slambench/kfusion/./include/default_parameters.h:15:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/vector:69:
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/vector.tcc:444:4: error: [Computecpp:CC0006]: Using exceptions is not allowed within SYCL device code
          __throw_exception_again;
          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/exception_defines.h:42:34: note: expanded from macro '__throw_exception_again'
# define __throw_exception_again throw
                                 ^
In file included from /home/dom/gu/Project/slambench/kfusion/src/stl/track.cpp:1:
In file included from /home/dom/gu/Project/slambench/kfusion/./include/kernels_stl.h:5:
In file included from /home/dom/gu/Project/slambench/kfusion/./include/commons.h:35:
In file included from /home/dom/gu/Project/slambench/kfusion/./include/default_parameters.h:15:
In file included from /usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/vector:69:
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/vector.tcc:408:7: error: [Computecpp:CC0006]: Using exceptions is not allowed within SYCL device code
      __try
      ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/7.2.0/../../../../include/c++/7.2.0/bits/exception_defines.h:40:21: note: expanded from macro '__try'
# define __try      try
                    ^
3 errors generated.
kfusion/CMakeFiles/kfusion-stl_track.cpp_2_ih.dir/build.make:61: recipe for target 'kfusion/track.cpp.sycl' failed
make[3]: *** [kfusion/track.cpp.sycl] Error 1
make[3]: Leaving directory '/home/dom/gu/Project/slambench/build'
CMakeFiles/Makefile2:555: recipe for target 'kfusion/CMakeFiles/kfusion-stl_track.cpp_2_ih.dir/all' failed
make[2]: *** [kfusion/CMakeFiles/kfusion-stl_track.cpp_2_ih.dir/all] Error 2
make[2]: Leaving directory '/home/dom/gu/Project/slambench/build'
Makefile:83: recipe for target 'all' failed
make[1]: *** [all] Error 2
make[1]: Leaving directory '/home/dom/gu/Project/slambench/build'
Makefile:14: recipe for target 'build' failed
make: *** [build] Error 2

I'm afraid that is a limitation of SYCL. You can't capture a std::vector in the lambda that will be your kernel, because it has a pointer field. You should try to make in an argument to std::experimental::parallel::transform, such that the appropriate element gets passed to the lambda along with the pixel id.

Oh, sorry, just saw that using two iterators is not an option.