kunzmi / managedCuda

ManagedCUDA aims an easy integration of NVidia's CUDA in .net applications written in C#, Visual Basic or any other .net language.
Other
440 stars 79 forks source link

Size of Boolean used to copy from host to device is 4 bytes. #51

Closed koonyook closed 7 years ago

koonyook commented 7 years ago

I randomly got this error while copying an array of bool from host to device.

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at ManagedCuda.DriverAPINativeMethods.SynchronousMemcpy_v2.cuMemcpyHtoD_v2(CUdeviceptr dstDevice, IntPtr srcHost, SizeT ByteCount) at ManagedCuda.CudaContext.CopyToDevice[T](CUdeviceptr aDest, T[] aSource) in i:\ManagedCuda\managedCuda\ManagedCUDA\CudaContext.cs:line 1521

I have found that if I just change from CudaDeviceVariable\<bool> to CudaDeviceVariable\<byte>, this error will not occur anymore.

This is because CudaDeviceVariable\<bool> has TypeSize of 4, it seems to copy more than it should. Therefore, it may attempt to read protected memory on the host and write to a protected memory on the device. However, CudaDeviceVariable\<byte> has TypeSize of 1, it will copy array of bool at the correct length.

kunzmi commented 7 years ago

The problem here is that bool or boolean in .net is not a blittable type, i.e. the .net representation is not identical to the C/C++ format. Usually in C bool has the size of 1 byte, why the CudaDeviceVariable<byte> works well. But be careful: std::vector<bool> can have the size of 1 bit only... In short: avoid working with bool in Cuda and .net when doing interop. Use unsigned char in Cuda and byte in C# instead to stay on the safe side.