use of org.apache.sysml.utils.LRUCacheMap in project incubator-systemml by apache.
the class GPUContext method evict.
/**
* Memory on the GPU is tried to be freed up until either a chunk of needed size is freed up
* or it fails.
* First the set of reusable blocks is freed up. If that isn't enough, the set of allocated matrix
* blocks with zero locks on them is freed up.
* The process cycles through the sorted list of allocated {@link GPUObject} instances. Sorting is based on
* number of (read) locks that have been obtained on it (reverse order). It repeatedly frees up
* blocks on which there are zero locks until the required size has been freed up.
* // TODO: update it with hybrid policy
*
* @param instructionName name of the instruction for which performance measurements are made
* @param neededSize desired size to be freed up on the GPU
* @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 {
LOG.trace("GPU : evict called from " + instructionName + " for size " + neededSize + " on " + this);
GPUStatistics.cudaEvictionCount.addAndGet(1);
// Release the set of free blocks maintained in a GPUObject.freeCUDASpaceMap
// to free up space
LRUCacheMap<Long, LinkedList<Pointer>> lruCacheMap = freeCUDASpaceMap;
while (lruCacheMap.size() > 0) {
if (neededSize <= getAvailableMemory())
break;
Map.Entry<Long, LinkedList<Pointer>> toFreeListPair = lruCacheMap.removeAndGetLRUEntry();
LinkedList<Pointer> toFreeList = toFreeListPair.getValue();
Long size = toFreeListPair.getKey();
Pointer toFree = toFreeList.pop();
if (toFreeList.isEmpty())
lruCacheMap.remove(size);
cudaFreeHelper(instructionName, toFree, true);
}
if (neededSize <= getAvailableMemory())
return;
if (allocatedGPUObjects.size() == 0) {
throw new DMLRuntimeException("There is not enough memory on device for this matrix, request (" + neededSize + ")");
}
Collections.sort(allocatedGPUObjects, new Comparator<GPUObject>() {
@Override
public int compare(GPUObject p1, GPUObject p2) {
long p1Val = p1.locks.get();
long p2Val = p2.locks.get();
if (p1Val > 0 && p2Val > 0) {
// Both are locked, so don't sort
return 0;
} else if (p1Val > 0 || p2Val > 0) {
// Put the unlocked one to RHS
return Long.compare(p2Val, p1Val);
} else {
if (evictionPolicy == EvictionPolicy.MIN_EVICT) {
long p1Size = 0;
long p2Size = 0;
try {
p1Size = p1.getSizeOnDevice() - neededSize;
p2Size = p2.getSizeOnDevice() - neededSize;
} catch (DMLRuntimeException e) {
throw new RuntimeException(e);
}
if (p1Size >= 0 && p2Size >= 0) {
return Long.compare(p2Size, p1Size);
} else {
return Long.compare(p1Size, p2Size);
}
} else if (evictionPolicy == EvictionPolicy.LRU || evictionPolicy == EvictionPolicy.LFU) {
return Long.compare(p2.timestamp.get(), p1.timestamp.get());
} else {
throw new RuntimeException("Unsupported eviction policy:" + evictionPolicy.name());
}
}
}
});
while (neededSize > getAvailableMemory() && allocatedGPUObjects.size() > 0) {
GPUObject toBeRemoved = allocatedGPUObjects.get(allocatedGPUObjects.size() - 1);
if (toBeRemoved.locks.get() > 0) {
throw new DMLRuntimeException("There is not enough memory on device for this matrix, request (" + neededSize + ")");
}
if (toBeRemoved.dirty) {
toBeRemoved.copyFromDeviceToHost();
}
toBeRemoved.clearData(true);
}
}
Aggregations