AnyDSL / thorin

The Higher-Order Intermediate Representation
https://anydsl.github.io
GNU Lesser General Public License v3.0
151 stars 15 forks source link

Runtime error passing mutable variable to a kernel function #51

Closed ergawy closed 7 years ago

ergawy commented 7 years ago

The following code:

extern "thorin" {
    fn nvvm(i32, (i32, i32, i32), (i32, i32, i32), fn() -> ()) -> ();
}

fn pass_dummy(mut d: i32) -> () { }

fn main() -> i32 {
    let mut d = 1;
    with nvvm(0, (1, 1, 1), (1, 1, 1)) {
        pass_dummy(d);
    }
    0
}

causes the runtime error:

Found return instr that returns non-void in Function of void return type! ret void voidBroken module found, compilation aborted!

This only happens if d is mut. If it is immutable it compiles fine.

Sometimes, the same thing causes another runtime error:

E:W:\thesis\anydsl\thorin\src\thorin\be\llvm\runtime.cpp: 91: currently only pointers to arrays supported as kernel argument at 'W:/thesis/anydsl/libpp/src/cuda/device/dispatch/dispatch_scan.impala:58 col 13 - 45'; argument has different type:

However, I couldn't reproduce this same issue in a stand alone example outside my code. If it is of any help, I can try to find out when either of the errors happen exactly.

richardmembarth commented 7 years ago

On master I get a different assertion:

Assertion failed: (I != ValueMap.end() && "Value not in slotcalculator!"), function getValueID, file llvm/lib/Bitcode/Writer/ValueEnumerator.cpp, line 135.
FanyuYe commented 7 years ago

I had met a lot the second compile error long times ago(only support pointer of array as kernel arg).

It happens if you try to use a member variable of a struct in the kernel(e.g. calling func_in_kernel(aStruct.memberVar);), and the aStruct is defined outside this kernel.

My silly workaround currently is:

// before calling kernel
let varToUse = aStruct.memberVar;
// in kernel
func_in_kernel(varToUse);

Hope this information helps :)

richardmembarth commented 7 years ago

The struct issue was a known issue for which we used the "magic_id" hack as a workaround. However, this is fixed on master since some time (one/two months or so).

The problem here is a pattern that is not allowed in CUDA/OpenCL: modifying a "host variable" on the GPU. The proper solution would be to:

Nevertheless, we should have a look at this.

ergawy commented 7 years ago

Thanks Fanyu for your help.

Actually, yes, I agree with Richard. Passing a mut struct from host to device should be seen as a bad practice. I didn't mean to modify the host variable on the device. The thing is, I modified the host variable twice before passing it to the device that's why I needed to make mut.

In that case, I guess it would be better to use pure functional form and pass the variable to the host function that modifies it. Then make the host function return a new struct that is received in an immutable variable.