You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@systemml.apache.org by na...@apache.org on 2017/09/19 21:57:53 UTC
systemml git commit: [MINOR] gpu memory leak fix
Repository: systemml
Updated Branches:
refs/heads/master f86879bd0 -> ec5dfda57
[MINOR] gpu memory leak fix
- Changed list of free pointers to set of free pointers for GPU
- Changed threadlocal cuda handles to non threadlocal. This is assuming there will be one thread per GPU.
Closes #665
Project: http://git-wip-us.apache.org/repos/asf/systemml/repo
Commit: http://git-wip-us.apache.org/repos/asf/systemml/commit/ec5dfda5
Tree: http://git-wip-us.apache.org/repos/asf/systemml/tree/ec5dfda5
Diff: http://git-wip-us.apache.org/repos/asf/systemml/diff/ec5dfda5
Branch: refs/heads/master
Commit: ec5dfda57a42b172886dd5d42bfe3b034b30c7b7
Parents: f86879b
Author: Nakul Jindal <na...@gmail.com>
Authored: Tue Sep 19 14:57:16 2017 -0700
Committer: Nakul Jindal <na...@gmail.com>
Committed: Tue Sep 19 14:57:16 2017 -0700
----------------------------------------------------------------------
src/main/cpp/CMakeLists.txt | 4 +-
.../instructions/gpu/context/GPUContext.java | 313 +++++++++++--------
2 files changed, 179 insertions(+), 138 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/systemml/blob/ec5dfda5/src/main/cpp/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/src/main/cpp/CMakeLists.txt b/src/main/cpp/CMakeLists.txt
index 47555bf..04e12b4 100644
--- a/src/main/cpp/CMakeLists.txt
+++ b/src/main/cpp/CMakeLists.txt
@@ -29,6 +29,7 @@ option(USE_INTEL_MKL "Whether to use Intel MKL (Defaults to compiling with Intel
# Build a shared libraray
add_library(systemml SHARED libmatrixdnn.cpp libmatrixmult.cpp systemml.cpp)
+set_target_properties(systemml PROPERTIES MACOSX_RPATH 1)
set(MATH_LIBRARIES "")
@@ -72,5 +73,6 @@ if (USE_OPEN_BLAS)
find_package(OpenMP REQUIRED)
set_target_properties(systemml PROPERTIES LINK_FLAGS "${OpenMP_CXX_FLAGS} ${MATH_LIBRARIES}")
elseif(USE_INTEL_MKL)
- set_target_properties(systemml PROPERTIES LINK_FLAGS ${MATH_LIBRARIES}")
+ set_target_properties(systemml PROPERTIES LINK_FLAGS "${MATH_LIBRARIES}")
endif()
+
http://git-wip-us.apache.org/repos/asf/systemml/blob/ec5dfda5/src/main/java/org/apache/sysml/runtime/instructions/gpu/context/GPUContext.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/sysml/runtime/instructions/gpu/context/GPUContext.java b/src/main/java/org/apache/sysml/runtime/instructions/gpu/context/GPUContext.java
index 271109d..8a823cc 100644
--- a/src/main/java/org/apache/sysml/runtime/instructions/gpu/context/GPUContext.java
+++ b/src/main/java/org/apache/sysml/runtime/instructions/gpu/context/GPUContext.java
@@ -41,9 +41,11 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
-import java.util.LinkedList;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -88,83 +90,50 @@ public class GPUContext {
* active device assigned to this GPUContext instance
*/
private final int deviceNum;
- // Invoke cudaMemGetInfo to get available memory information. Useful if GPU is shared among multiple application.
- public double GPU_MEMORY_UTILIZATION_FACTOR = ConfigurationManager.getDMLConfig()
- .getDoubleValue(DMLConfig.GPU_MEMORY_UTILIZATION_FACTOR);
- /**
- * Map of free blocks allocate on GPU. maps size_of_block -> pointer on GPU
- */
- private LRUCacheMap<Long, LinkedList<Pointer>> freeCUDASpaceMap = new LRUCacheMap<>();
- /**
- * To record size of allocated blocks
- */
- private HashMap<Pointer, Long> cudaBlockSizeMap = new HashMap<>();
- /**
- * list of allocated {@link GPUObject} instances allocated on {@link GPUContext#deviceNum} GPU
- * These are matrices allocated on the GPU on which rmvar hasn't been called yet.
- * If a {@link GPUObject} has more than one lock on it, it cannot be freed
- * If it has zero locks on it, it can be freed, but it is preferrable to keep it around
- * so that an extraneous host to dev transfer can be avoided
- */
- private ArrayList<GPUObject> allocatedGPUObjects = new ArrayList<>();
/**
* cudnnHandle for Deep Neural Network operations on the GPU
*/
- private final ThreadLocal<cudnnHandle> cudnnHandle = new ThreadLocal<>();
+ private cudnnHandle cudnnHandle;
/**
* cublasHandle for BLAS operations on the GPU
*/
- private final ThreadLocal<cublasHandle> cublasHandle = new ThreadLocal<>();
+ private cublasHandle cublasHandle;
/**
* cusparseHandle for certain sparse BLAS operations on the GPU
*/
- private final ThreadLocal<cusparseHandle> cusparseHandle = new ThreadLocal<>();
+ private cusparseHandle cusparseHandle;
/**
* cusolverDnHandle for invoking solve() function on dense matrices on the GPU
*/
- private final ThreadLocal<cusolverDnHandle> cusolverDnHandle = new ThreadLocal<>();
+ private cusolverDnHandle cusolverDnHandle;
/**
* cusolverSpHandle for invoking solve() function on sparse matrices on the GPU
*/
- private final ThreadLocal<cusolverSpHandle> cusolverSpHandle = new ThreadLocal<>();
+ private cusolverSpHandle cusolverSpHandle;
/**
* to launch custom CUDA kernel, specific to the active GPU for this GPUContext
*/
- private final ThreadLocal<JCudaKernels> kernels = new ThreadLocal<>();
-
+ private JCudaKernels kernels;
+
+ // Invoke cudaMemGetInfo to get available memory information. Useful if GPU is shared among multiple application.
+ public double GPU_MEMORY_UTILIZATION_FACTOR = ConfigurationManager.getDMLConfig()
+ .getDoubleValue(DMLConfig.GPU_MEMORY_UTILIZATION_FACTOR);
/**
- * Print information of memory usage.
- *
- * @param opcode opcode of caller
- * @throws DMLRuntimeException if error
+ * Map of free blocks allocate on GPU. maps size_of_block -> pointer on GPU
*/
- public void printMemoryInfo(String opcode) throws DMLRuntimeException {
- if(LOG.isDebugEnabled()) {
- long totalFreeCUDASpace = 0;
- for(Entry<Long, LinkedList<Pointer>> kv : freeCUDASpaceMap.entrySet()) {
- totalFreeCUDASpace += kv.getKey()*kv.getValue().size();
- }
- long readLockedAllocatedMemory = 0;
- long writeLockedAllocatedMemory = 0;
- long unlockedAllocatedMemory = 0;
- for(GPUObject gpuObj : allocatedGPUObjects) {
- if(gpuObj.readLocks.longValue() > 0)
- readLockedAllocatedMemory += gpuObj.getSizeOnDevice();
- else if(gpuObj.writeLock)
- writeLockedAllocatedMemory += gpuObj.getSizeOnDevice();
- else
- unlockedAllocatedMemory += gpuObj.getSizeOnDevice();
- }
- long free[] = { 0 };
- long total[] = { 0 };
- cudaMemGetInfo(free, total);
- long gpuFreeMemory = (long) (free[0] * GPU_MEMORY_UTILIZATION_FACTOR);
- LOG.debug(opcode + ": Total memory: " + total[0] + ", Free memory: " + free[0] + " (with util factor: " + gpuFreeMemory + "), "
- + "Lazy unfreed memory: " + totalFreeCUDASpace + ", Locked allocated memory (read/write): "
- + readLockedAllocatedMemory + "/" + writeLockedAllocatedMemory + ", "
- + " Unlocked allocated memory: " + unlockedAllocatedMemory);
- }
- }
+ private LRUCacheMap<Long, Set<Pointer>> freeCUDASpaceMap = new LRUCacheMap<>();
+ /**
+ * To record size of allocated blocks
+ */
+ private HashMap<Pointer, Long> cudaBlockSizeMap = new HashMap<>();
+ /**
+ * list of allocated {@link GPUObject} instances allocated on {@link GPUContext#deviceNum} GPU
+ * These are matrices allocated on the GPU on which rmvar hasn't been called yet.
+ * If a {@link GPUObject} has more than one lock on it, it cannot be freed
+ * If it has zero locks on it, it can be freed, but it is preferrable to keep it around
+ * so that an extraneous host to dev transfer can be avoided
+ */
+ private ArrayList<GPUObject> allocatedGPUObjects = new ArrayList<>();
protected GPUContext(int deviceNum) throws DMLRuntimeException {
this.deviceNum = deviceNum;
@@ -187,61 +156,97 @@ public class GPUContext {
LOG.info(" GPU memory - Total: " + (total[0] * (1e-6)) + " MB, Available: " + (free[0] * (1e-6)) + " MB on "
+ this);
- if(GPUContextPool.initialGPUMemBudget() > OptimizerUtils.getLocalMemBudget()) {
- LOG.warn("Potential under-utilization: GPU memory (" + GPUContextPool.initialGPUMemBudget()
+ if (GPUContextPool.initialGPUMemBudget() > OptimizerUtils.getLocalMemBudget()) {
+ LOG.warn("Potential under-utilization: GPU memory (" + GPUContextPool.initialGPUMemBudget()
+ ") > driver memory budget (" + OptimizerUtils.getLocalMemBudget() + "). "
+ "Consider increasing the driver memory budget.");
}
}
+ /**
+ * Returns which device is currently being used.
+ *
+ * @return the current device for the calling host thread
+ */
+ public static int cudaGetDevice() {
+ int[] device = new int[1];
+ JCuda.cudaGetDevice(device);
+ return device[0];
+ }
+
+ /**
+ * Print information of memory usage.
+ *
+ * @param opcode opcode of caller
+ * @throws DMLRuntimeException if error
+ */
+ public void printMemoryInfo(String opcode) throws DMLRuntimeException {
+ if (LOG.isDebugEnabled()) {
+ long totalFreeCUDASpace = 0;
+ for (Entry<Long, Set<Pointer>> kv : freeCUDASpaceMap.entrySet()) {
+ totalFreeCUDASpace += kv.getKey() * kv.getValue().size();
+ }
+ long readLockedAllocatedMemory = 0;
+ long writeLockedAllocatedMemory = 0;
+ long unlockedAllocatedMemory = 0;
+ for (GPUObject gpuObj : allocatedGPUObjects) {
+ if (gpuObj.readLocks.longValue() > 0)
+ readLockedAllocatedMemory += gpuObj.getSizeOnDevice();
+ else if (gpuObj.writeLock)
+ writeLockedAllocatedMemory += gpuObj.getSizeOnDevice();
+ else
+ unlockedAllocatedMemory += gpuObj.getSizeOnDevice();
+ }
+ long free[] = { 0 };
+ long total[] = { 0 };
+ cudaMemGetInfo(free, total);
+ long gpuFreeMemory = (long) (free[0] * GPU_MEMORY_UTILIZATION_FACTOR);
+ LOG.debug(opcode + ": Total memory: " + total[0] + ", Free memory: " + free[0] + " (with util factor: "
+ + gpuFreeMemory + "), " + "Lazy unfreed memory: " + totalFreeCUDASpace
+ + ", Locked allocated memory (read/write): " + readLockedAllocatedMemory + "/"
+ + writeLockedAllocatedMemory + ", " + " Unlocked allocated memory: " + unlockedAllocatedMemory);
+ }
+ }
+
private void initializeCudaLibraryHandles() throws DMLRuntimeException {
- if (cudnnHandle.get() == null) {
- cudnnHandle.set(new cudnnHandle());
- cudnnCreate(cudnnHandle.get());
+ deleteCudaLibraryHandles();
+
+ if (cudnnHandle == null) {
+ cudnnHandle = new cudnnHandle();
+ cudnnCreate(cudnnHandle);
}
- if (cublasHandle.get() == null) {
- cublasHandle.set(new cublasHandle());
- cublasCreate(cublasHandle.get());
+ if (cublasHandle == null) {
+ cublasHandle = new cublasHandle();
+ cublasCreate(cublasHandle);
}
// For cublas v2, cublasSetPointerMode tells Cublas whether to expect scalar arguments on device or on host
// This applies to arguments like "alpha" in Dgemm, and "y" in Ddot.
// cublasSetPointerMode(LibMatrixCUDA.cublasHandle, cublasPointerMode.CUBLAS_POINTER_MODE_DEVICE);
- if (cusparseHandle.get() == null) {
- cusparseHandle.set(new cusparseHandle());
- cusparseCreate(cusparseHandle.get());
+ if (cusparseHandle == null) {
+ cusparseHandle = new cusparseHandle();
+ cusparseCreate(cusparseHandle);
}
- if (cusolverDnHandle.get() == null) {
- cusolverDnHandle.set(new cusolverDnHandle());
- cusolverDnCreate(cusolverDnHandle.get());
+ if (cusolverDnHandle == null) {
+ cusolverDnHandle = new cusolverDnHandle();
+ cusolverDnCreate(cusolverDnHandle);
}
- if (cusolverSpHandle.get() == null) {
- cusolverSpHandle.set(new cusolverSpHandle());
- cusolverSpCreate(cusolverSpHandle.get());
+ if (cusolverSpHandle == null) {
+ cusolverSpHandle = new cusolverSpHandle();
+ cusolverSpCreate(cusolverSpHandle);
}
- if (kernels.get() == null) {
- kernels.set(new JCudaKernels());
+ if (kernels == null) {
+ kernels = new JCudaKernels();
}
}
/**
- * Returns which device is currently being used.
- *
- * @return the current device for the calling host thread
- */
- public static int cudaGetDevice() {
- int[] device = new int[1];
- JCuda.cudaGetDevice(device);
- return device[0];
- }
-
- /**
* Returns which device is assigned to this GPUContext instance.
- *
+ *
* @return active device assigned to this GPUContext instance
*/
public int getDeviceNum() {
@@ -254,7 +259,7 @@ public class GPUContext {
* {@link org.apache.sysml.runtime.controlprogram.context.ExecutionContext#getGPUContext(int)}
* If in a multi-threaded environment like parfor, this method must be called when in the
* appropriate thread.
- *
+ *
* @throws DMLRuntimeException if DMLRuntimeException occurs
*/
public void initializeThread() throws DMLRuntimeException {
@@ -300,24 +305,29 @@ public class GPUContext {
long t0 = 0, t1 = 0, end = 0;
Pointer A;
if (freeCUDASpaceMap.containsKey(size)) {
- if(LOG.isTraceEnabled()) {
- LOG.trace("GPU : in allocate from instruction " + instructionName + ", found free block of size " + (size
- / 1024.0) + " Kbytes from previously allocated block on " + this);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace(
+ "GPU : in allocate from instruction " + instructionName + ", found free block of size " + (size
+ / 1024.0) + " Kbytes from previously allocated block on " + this);
}
if (instructionName != null && GPUStatistics.DISPLAY_STATISTICS)
t0 = System.nanoTime();
- LinkedList<Pointer> freeList = freeCUDASpaceMap.get(size);
- A = freeList.pop();
+ Set<Pointer> freeList = freeCUDASpaceMap.get(size);
+
+ Iterator<Pointer> it = freeList.iterator(); // at this point, freeList should have at least one element
+ A = it.next();
+ it.remove();
+
if (freeList.isEmpty())
freeCUDASpaceMap.remove(size);
if (instructionName != null && GPUStatistics.DISPLAY_STATISTICS)
GPUStatistics
- .maintainCPMiscTimes(instructionName, GPUInstruction.MISC_TIMER_REUSE, System.nanoTime() - t0);
+ .maintainCPMiscTimes(instructionName, GPUInstruction.MISC_TIMER_REUSE, System.nanoTime() - t0);
} else {
- if(LOG.isTraceEnabled()) {
+ if (LOG.isTraceEnabled()) {
LOG.trace(
- "GPU : in allocate from instruction " + instructionName + ", allocating new block of size " + (size
- / 1024.0) + " Kbytes on " + this);
+ "GPU : in allocate from instruction " + instructionName + ", allocating new block of size " + (
+ size / 1024.0) + " Kbytes on " + this);
}
if (DMLScript.STATISTICS)
t0 = System.nanoTime();
@@ -335,9 +345,9 @@ public class GPUContext {
// Set all elements to 0 since newly allocated space will contain garbage
if (DMLScript.STATISTICS)
t1 = System.nanoTime();
- if(LOG.isTraceEnabled()) {
- LOG.trace("GPU : in allocate from instruction " + instructionName + ", setting block of size " + (size / 1024.0)
- + " Kbytes to zero on " + this);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("GPU : in allocate from instruction " + instructionName + ", setting block of size " + (size
+ / 1024.0) + " Kbytes to zero on " + this);
}
cudaMemset(A, 0, size);
if (DMLScript.STATISTICS)
@@ -394,13 +404,14 @@ public class GPUContext {
if (toFree == dummy) // trying to free a null pointer
return;
long t0 = 0;
- if(!cudaBlockSizeMap.containsKey(toFree))
- throw new RuntimeException("ERROR : Internal state corrupted, cache block size map is not aware of a block it trying to free up");
+ if (!cudaBlockSizeMap.containsKey(toFree))
+ throw new RuntimeException(
+ "ERROR : Internal state corrupted, cache block size map is not aware of a block it trying to free up");
long size = cudaBlockSizeMap.get(toFree);
if (eager) {
- if(LOG.isTraceEnabled()) {
- LOG.trace("GPU : eagerly freeing cuda memory [ " + toFree + " ] for instruction " + instructionName + " on "
- + this);
+ if (LOG.isTraceEnabled()) {
+ LOG.trace("GPU : eagerly freeing cuda memory [ " + toFree + " ] for instruction " + instructionName
+ + " on " + this);
}
if (DMLScript.STATISTICS)
t0 = System.nanoTime();
@@ -414,12 +425,12 @@ public class GPUContext {
GPUStatistics.maintainCPMiscTimes(instructionName, GPUInstruction.MISC_TIMER_CUDA_FREE,
System.nanoTime() - t0);
} else {
- if(LOG.isTraceEnabled()) {
+ if (LOG.isTraceEnabled()) {
LOG.trace("GPU : lazily freeing cuda memory for instruction " + instructionName + " on " + this);
}
- LinkedList<Pointer> freeList = freeCUDASpaceMap.get(size);
+ Set<Pointer> freeList = freeCUDASpaceMap.get(size);
if (freeList == null) {
- freeList = new LinkedList<Pointer>();
+ freeList = new HashSet<>();
freeCUDASpaceMap.put(size, freeList);
}
if (freeList.contains(toFree))
@@ -446,7 +457,7 @@ public class GPUContext {
* @throws DMLRuntimeException if DMLRuntimeException occurs
*/
void ensureFreeSpace(String instructionName, long size) throws DMLRuntimeException {
- if(size < 0 )
+ if (size < 0)
throw new DMLRuntimeException("The size cannot be negative:" + size);
else if (size >= getAvailableMemory())
evict(instructionName, size);
@@ -477,20 +488,24 @@ public class GPUContext {
* @throws DMLRuntimeException If no reusable memory blocks to free up or if not enough matrix blocks with zero locks on them.
*/
protected void evict(String instructionName, final long neededSize) throws DMLRuntimeException {
- if(LOG.isTraceEnabled()) {
+ if (LOG.isTraceEnabled()) {
LOG.trace("GPU : evict called from " + instructionName + " for size " + neededSize + " on " + this);
}
GPUStatistics.cudaEvictionCount.add(1);
// Release the set of free blocks maintained in a GPUObject.freeCUDASpaceMap
// to free up space
- LRUCacheMap<Long, LinkedList<Pointer>> lruCacheMap = freeCUDASpaceMap;
+ LRUCacheMap<Long, Set<Pointer>> lruCacheMap = freeCUDASpaceMap;
while (lruCacheMap.size() > 0) {
if (neededSize <= getAvailableMemory())
break;
- Map.Entry<Long, LinkedList<Pointer>> toFreeListPair = lruCacheMap.removeAndGetLRUEntry();
- LinkedList<Pointer> toFreeList = toFreeListPair.getValue();
+ Map.Entry<Long, Set<Pointer>> toFreeListPair = lruCacheMap.removeAndGetLRUEntry();
+ Set<Pointer> toFreeList = toFreeListPair.getValue();
Long size = toFreeListPair.getKey();
- Pointer toFree = toFreeList.pop();
+
+ Iterator<Pointer> it = toFreeList.iterator(); // at this point, freeList should have at least one element
+ Pointer toFree = it.next();
+ it.remove();
+
if (toFreeList.isEmpty())
lruCacheMap.remove(size);
cudaFreeHelper(instructionName, toFree, true);
@@ -548,7 +563,8 @@ public class GPUContext {
GPUObject toBeRemoved = allocatedGPUObjects.get(allocatedGPUObjects.size() - 1);
if (toBeRemoved.isLocked()) {
throw new DMLRuntimeException(
- "There is not enough memory on device for this matrix, request (" + neededSize + "). Allocated GPU objects:" + allocatedGPUObjects.toString());
+ "There is not enough memory on device for this matrix, request (" + neededSize
+ + "). Allocated GPU objects:" + allocatedGPUObjects.toString());
}
if (toBeRemoved.dirty) {
toBeRemoved.copyFromDeviceToHost();
@@ -629,7 +645,7 @@ public class GPUContext {
/**
* Instantiates a new {@link GPUObject} initialized with the given {@link org.apache.sysml.runtime.controlprogram.caching.MatrixObject MatrixObject}.
- *
+ *
* @param mo a {@link org.apache.sysml.runtime.controlprogram.caching.MatrixObject MatrixObject} that represents a matrix
* @return a new {@link GPUObject} instance
*/
@@ -693,56 +709,56 @@ public class GPUContext {
/**
* Returns the cudnnHandle for Deep Neural Network operations on the GPU.
- *
+ *
* @return cudnnHandle for current thread
*/
public cudnnHandle getCudnnHandle() {
- return cudnnHandle.get();
+ return cudnnHandle;
}
/**
* Returns cublasHandle for BLAS operations on the GPU.
- *
+ *
* @return cublasHandle for current thread
*/
public cublasHandle getCublasHandle() {
- return cublasHandle.get();
+ return cublasHandle;
}
/**
* Returns cusparseHandle for certain sparse BLAS operations on the GPU.
- *
+ *
* @return cusparseHandle for current thread
*/
public cusparseHandle getCusparseHandle() {
- return cusparseHandle.get();
+ return cusparseHandle;
}
/**
* Returns cusolverDnHandle for invoking solve() function on dense matrices on the GPU.
- *
+ *
* @return cusolverDnHandle for current thread
*/
public cusolverDnHandle getCusolverDnHandle() {
- return cusolverDnHandle.get();
+ return cusolverDnHandle;
}
/**
* Returns cusolverSpHandle for invoking solve() function on sparse matrices on the GPU.
- *
+ *
* @return cusolverSpHandle for current thread
*/
public cusolverSpHandle getCusolverSpHandle() {
- return cusolverSpHandle.get();
+ return cusolverSpHandle;
}
/**
* Returns utility class used to launch custom CUDA kernel, specific to the active GPU for this GPUContext.
- *
+ *
* @return {@link JCudaKernels} for current thread
*/
public JCudaKernels getKernels() {
- return kernels.get();
+ return kernels;
}
/**
@@ -751,15 +767,38 @@ public class GPUContext {
* @throws DMLRuntimeException if error
*/
public void destroy() throws DMLRuntimeException {
- if(LOG.isTraceEnabled()) {
+ if (LOG.isTraceEnabled()) {
LOG.trace("GPU : this context was destroyed, this = " + this.toString());
}
clearMemory();
- cudnnDestroy(cudnnHandle.get());
- cublasDestroy(cublasHandle.get());
- cusparseDestroy(cusparseHandle.get());
- cusolverDnDestroy(cusolverDnHandle.get());
- cusolverSpDestroy(cusolverSpHandle.get());
+
+ deleteCudaLibraryHandles();
+ }
+
+ /**
+ * Deletes CUDA library handles
+ */
+ private void deleteCudaLibraryHandles() {
+ if (cudnnHandle != null)
+ cudnnDestroy(cudnnHandle);
+
+ if (cublasHandle != null)
+ cublasDestroy(cublasHandle);
+
+ if (cusparseHandle != null)
+ cusparseDestroy(cusparseHandle);
+
+ if (cusolverDnHandle != null)
+ cusolverDnDestroy(cusolverDnHandle);
+
+ if (cusolverSpHandle != null)
+ cusolverSpDestroy(cusolverSpHandle);
+
+ cudnnHandle = null;
+ cublasHandle = null;
+ cusparseHandle = null;
+ cusolverDnHandle = null;
+ cusolverSpHandle = null;
}
/**
@@ -817,7 +856,7 @@ public class GPUContext {
}
// garbage collect all temporarily allocated spaces
- for (LinkedList<Pointer> l : freeCUDASpaceMap.values()) {
+ for (Set<Pointer> l : freeCUDASpaceMap.values()) {
for (Pointer p : l) {
cudaFreeHelper(p, true);
}