Trying to use unified memory


#1

hello,

the usage of unified memory assumes that I don’t need to copy data (cuMemCpu) between host and device.

Typical usage of array allocating is

double CPUarray[]=new double[100];
CUdeviceptr ptr=new CUdeviceptr();
cuMemAlloc(ptr, CPUarray.length*Sizeof.DOUBLE);
cuMemcpyHtoD(ptr, Pointer.to(CPUarray), CPUarray.length*Sizeof.DOUBLE);

Unified Memory (minimum requirements is compute capability 3.0) usage is

double CPUarray[]=new double[100];
CUdeviceptr ptr=new CUdeviceptr();
cuMemAllocManaged(ptr, CPUarray.length*Sizeof.DOUBLE, 0);

So the problem is the ‘cuMemAllocManaged’ require the ‘CUdeviceptr ptr’ and I can’t make relation between ‘CUdeviceptr ptr’ and ‘double CPUarray[]’. This relation I can make in ‘cuMemcpyHtoD’ but the sense of Unified Memory is the absence of ‘cuMemcpyHtoD’.

Another way is the usage ‘Pointer.to(CPUarray)’ but ‘cuMemAllocManaged’ pointer should be of ‘CUdeviceptr’ type.

Thank you!


#2

Hello

First of all, I have to mention that I have not yet really used the Unified Memory functionality (because it is relatively new, and my hardware is … rather old -_- )

But in general, there is no real “relation” between the memory that is allocated with CUDA, and a Java array. When you allocate managed memory with

cuMemAllocManaged(ptr, CPUarray.length*Sizeof.DOUBLE, 0);

then you simply cannot access this as a java [inline]double[][/inline] array: The managed memory is handled by CUDA. But a Java array is managed by the Java Virtual Machine (JVM).

However, you can* access this memory from Java: You can call Pointer#getByteBuffer on this pointer. This [inline]ByteBuffer[/inline] can then be viewn as a [inline]DoubleBuffer[/inline], and with this buffer, you can read/write data from/to the managed memory from Java:

cuMemAllocManaged(ptr, CPUarray.length*Sizeof.DOUBLE, 0);
ByteBuffer bb = ptr.toByteBuffer(0, CPUarray.length*Sizeof.DOUBLE);
DoubleBuffer db = bb.order(ByteOrder.nativeOrder()).asDoubleBuffer();

db.put(index, 123.456); // Write to unified memory
double d = db.get(index); // Read from unified memory

I know that this somewhat limits the application scope: When a Java method creates or expects a [inline]double[][/inline] array, then this can not easily be replaced with CUDA managed memory. But there is no way to circumvent that, because the fact that Java arrays always have to be handled solely by the JVM can not be changed…

*: Again, I could not test this myself, but it should work this way…