denzp / rust-ptx-linker

The missing puzzle piece for NVPTX experience with Rust
MIT License
52 stars 11 forks source link

`panic!` causes infinite loop #21

Open bheisler opened 6 years ago

bheisler commented 6 years ago

It seems that panics are handled by infinite-looping. This makes sense in some situations, but on CUDA we can do better. CUDA does support printing output to stdout (though I haven't figured out how to do so in rust yet, since the println! macro depends on std). Afterwards, we can terminate the kernel using inline assembly, like so: asm!("trap;");. This terminates the kernel with an (admittedly unclear) error message regarding an illegal instruction. This is a pretty common way to forcefully terminate a kernel (see stackoverflow for example).

denzp commented 6 years ago

Thanks, it's a good suggestion!

#[no_mangle]
pub unsafe extern "ptx-kernel" fn test() {
    use core::intrinsics::breakpoint;

    breakpoint();
}

generates the trap instruction:

.visible .entry test()
{
    trap;
    ret;
}

I'll try to experiment with printing from kernels and then will make corresponding changes.

denzp commented 6 years ago

According to ptx guide we can declare external vprintf and then call it with proper arguments. Had to make changes to the linker to not report vprintf as an undefined external function, though.

use core::intrinsics::breakpoint;

extern "C" {
    fn vprintf(format: *const u8, va: *const u8) -> i32;
}

pub unsafe fn kernel() {
    vprintf(
        "from kernel: %d %d\n".as_ptr(),
        [0u32, 1u32].as_ptr() as *const u8,
    );

    breakpoint();
}

I saw text "from kernel: 0 1" printed to stdout and then the kernel was terminated with LaunchFailed error.

Maybe there is a no_std crate that implements safe println macro and can use custom "backend"?

bheisler commented 6 years ago

Yeah, I certainly wouldn't want to have to manually call vprintf. I think special-casing it in the linker makes sense, though.

I agree that a macro is probably the best way to expose this to the programmer. I think it would have to be a procedural macro, though - in order to provide a safe interface (ie. one without undefined behavior), you'd have to either parse the Rust-style format string/argument types and substitute in appropriate C-style format specifiers, or parse a C-style format string and check that the values are the right type.

denzp commented 6 years ago

I started to work on development ergonomics improvement. You can already find implemented safe cuda_printf! macro. The crate is not yet published, because there are many major changes coming soon.