This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Problem with vector and cilk_spawn


On 2017-03-09 23:36 +0100, Florent Hivert wrote:

> It seems that there is a problem with dynamic allocation and cilk_spawn. The
> following code fails randomly with GCC-6 and GCC-7 (it fails with ICE on
> GCC-5). It works without any problems on one core machine. Some times it works
> perfectly, some times it segfault. I also had some double free failure.

> #include <vector>
> #include <cilk/cilk.h>
> 
> void walk(std::vector<int> v, unsigned size) {
>   if (v.size() < size)
>     for (int i=0; i<8; i++) {
>       std::vector<int> vnew(v);
>       vnew.push_back(i);
>       cilk_spawn walk(vnew, size);
>     }
> }
> 
> int main(int argc, char **argv) {
>   std::vector<int> v{};
>   walk(v, 5);
> }

Compile with "-fsanitize=thread", and run it. It would produce a lot of
"data race" warning, like:
~~~
WARNING: ThreadSanitizer: data race (pid=5645)
  Read of size 8 at 0x7ffcc2743098 by thread T1:
    #0 std::vector<int, std::allocator<int> >::~vector() /usr/include/c++/6.3.0/bits/stl_vector.h:426
(a.out+0x000000401b6f)
    #1 walk(std::vector<int, std::allocator<int> >, unsigned int) /home/xry111/cilk.cpp:9 (a.out+0x00000040110a)

  Previous write of size 8 at 0x7ffcc2743098 by main thread:
    #0 std::_Vector_base<int, std::allocator<int> >::_Vector_impl::_Vector_impl(std::allocator<int> const&)
/usr/include/c++/6.3.0/bits/stl_vector.h:91 (a.out+0x00000040240f)
    #1 std::_Vector_base<int, std::allocator<int> >::_Vector_base(unsigned long, std::allocator<int> const&)
/usr/include/c++/6.3.0/bits/stl_vector.h:135 (a.out+0x000000401d9b)
    #2 std::vector<int, std::allocator<int> >::vector(std::vector<int, std::allocator<int> > const&)
/usr/include/c++/6.3.0/bits/stl_vector.h:322 (a.out+0x000000401a78)
    #3 walk(std::vector<int, std::allocator<int> >, unsigned int) /home/xry111/cilk.cpp:9 (a.out+0x00000040109e)
    #4 main /home/xry111/cilk.cpp:15 (a.out+0x00000040162b)

  Location is stack of main thread.
~~~

After peeking into the assembly code, I found "cilk_spawn walk" is compiled to

  1) copy vnew to a temp vector _tmp1_.
  2) call _cilk_spn_1 with the address (reference) of _tmp1_.
     cilk_spn_1 creates a thread running walk, with the reference of tmp1, then return.
  3) destruct _tmp1_.  But at this point, the new thread created by cilkplus is still
     holding the reference to _tmp1_. So strange things would happen.

I don't have a cilkplus standard so I don't know the expected behaviour of this. If
the standard tells us this should work, we'll have to copy the vector to the stack of
the new thread in GCC. If the standard prohibits this, we'll have to use something
like reference counting.

-- 
Xi Ruoyao <ryxi@stu.xidian.edu.cn>
School of Aerospace Science and Technology, Xidian University


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]