weld-project / weld

High-performance runtime for data analytics applications
https://www.weld.rs
BSD 3-Clause "New" or "Revised" License
3k stars 257 forks source link

Segmentation Fault in program using groupmerger and appender #363

Open mihai-varga opened 6 years ago

mihai-varga commented 6 years ago

The Weld program below generates a seg fault when running on multiple threads and the input size is sufficiently large (len(x) ~ 1mil)

|x:vec[i64], mod:i64|
let table = result(
    for(x, groupmerger[i64, i64], |b, i, n|
        merge(b, {n % mod, i})
    )
);
let join = for(rangeiter(0L, mod, 1L), {appender[i64], appender[i64]}, |b, i, n|
    if(keyexists(table, n),
        for(lookup(table, n), b, |b1, i1, n1|
            {merge(b1.$0, n1), merge(b1.$1, i)}
        ),
        b
    )
);
let left = for(result(join.$0), appender[i64], |b, i, n|
    merge(b, n)
);
let right = for(result(join.$1), appender[i64], |b, i, n|
    merge(b, n)
);
{result(left), result(right)}

It's not easy to reproduce on my machine and if I replace left and right with let left = join.$0; let right = join.$1 it seems to work just fine. you can see the whole C code here: https://pastebin.com/9VGNbs02

mihai-varga commented 6 years ago

I can actually get the seg fault in 2 locations:

1)

*** Error in `./out': corrupted double-linked list: 0x0000000001818d30 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x7cbac)[0x7f15bf437bac]
/lib64/libc.so.6(+0x8847b)[0x7f15bf44347b]
/lib64/libc.so.6(cfree+0x16e)[0x7f15bf4483be]
/export/scratch1/mihai/weld/my/lib/libweld.so(weld_rt_result_vb+0x985)[0x7f15bfa14255]

the traced execution ended in:

merge(b__2, n__2)
  end
  merge(b__2, n__2)
  end
  for [fringeiter(a), ] fn7_tmp__2 b__3 i__3 n__3 F10 F11 true
  fn11_tmp = result(fn7_tmp__2)
  fn11_tmp__1 = join.$1
  fn11_tmp__2 = result(fn11_tmp__1)

2)

#0  0x00007ffff6aa6812 in weld_rt_new_vb_piece () from /export/scratch1/mihai/weld/my/lib/libweld.so
#1  0x00007ffff7ff3e08 in f9_par ()
#2  0x00007ffff6aa95fa in work_loop(int, run_data*) () from /export/scratch1/mihai/weld/my/lib/libweld.so
#3  0x00007ffff6aa8c05 in thread_func(void*) () from /export/scratch1/mihai/weld/my/lib/libweld.so

and the trace ends in:

  merge(b__2, n__2)
  end
  merge(b__2, n__2)
  end
  merg

The optimized program is:

|x:vec[i64],mod:i64|
  (let table:dict[i64,vec[i64]]=(result(
    for(
      x:vec[i64],
      groupmerger[i64,i64],
      |b:groupmerger[i64,i64],i:i64,n:i64|
        merge(b:groupmerger[i64,i64],{(n:i64%mod:i64),i:i64})
    )
  ));(let join:{appender[i64],appender[i64]}=(for(
    rangeiter([],0L,mod:i64,1L),
    {appender[i64],appender[i64]},
    |b__1:{appender[i64],appender[i64]},i__1:i64,n__1:i64|
      if(
        keyexists(table:dict[i64,vec[i64]],n__1:i64),
        for(
          lookup(table:dict[i64,vec[i64]],n__1:i64),
          b__1:{appender[i64],appender[i64]},
          |b1:{appender[i64],appender[i64]},i1:i64,n1:i64|
            {merge(b1.$0,n1:i64),merge(b1.$1,i__1:i64)}
        ),
        b__1:{appender[i64],appender[i64]}
      )
  ));{result(
    (let a:vec[i64]=(result(
      join.$0
    ));for(
      fringeiter(a:vec[i64]),
      for(
        simditer(a:vec[i64]),
        appender[i64],
        |b__2:appender[i64],i__2:i64,n__2:simd[i64]|
          merge(b__2:appender[i64],n__2:simd[i64])
      ),
      |b__3:appender[i64],i__3:i64,n__3:i64|
        merge(b__3:appender[i64],n__3:i64)
    ))
  ),result(
    (let a__1:vec[i64]=(result(
      join.$1
    ));for(
      fringeiter(a__1:vec[i64]),
      for(
        simditer(a__1:vec[i64]),
        appender[i64],
        |b__4:appender[i64],i__4:i64,n__4:simd[i64]|
          merge(b__4:appender[i64],n__4:simd[i64])
      ),
      |b__5:appender[i64],i__5:i64,n__5:i64|
        merge(b__5:appender[i64],n__5:i64)
    ))
  )}))