There is a similar bug in CUDALink. It appears to be related to memory management of MTensor objects passed back to Mathematica from the CUDALink or OpenCLLink library. The problem, as far as I can tell, arises due to the LibraryFunction defined in OpenCLLink`Private`cGetMemory["Double"]
which specifies a shared return. This means that the library will keep ownership of the returned MTensor until it is explicitly disowned. Presumably there is a bug in the library code so that it never disowns the MTensor and the memory is never freed.
My workaround is to unload the cGetMemory
function and then reload it, specifying automatic return instead of shared return. This should cause the library to lose ownership of the MTensor when it is returned to Mathematica, so the memory will be freed as soon as Mathematica has done with it.
Example:
Needs["OpenCLLink`"];
(* kernel memory grows by size of returned array on every call *)
Table[OpenCLMersenneTwister[100000]; MemoryInUse[], {5}] // Differences
(* {820520, 819352, 819352, 819352} *)
(* apply the fix *)
With[{func := OpenCLLink`Private`cGetMemory["Double"]},
Module[{args = List @@ func},
LibraryFunctionUnload[func];
func = LibraryFunctionLoad @@ Delete[args, {4, 3}]]];
(* kernel memory is now under control *)
Table[OpenCLMersenneTwister[100000]; MemoryInUse[], {5}] // Differences
(* {16, 16, 16, 16} *)
If your GPU is single precision only you probably need to use "Single" instead of "Double". To similarly patch CUDALink just put CUDALink
in place of OpenCLLink
.
I can't be certain that there aren't any nasty side effects to this workaround, as I don't understand LibraryLink very well, but I have used this fix on CUDALink and been able to run code for >24 hours, transferring tens of gigabytes from the GPU back to host memory without the Mathematica kernel running out of memory.