Я создаю оболочку Scala вокруг библиотек Torch .Я использую Swig , чтобы создать слой клея.Это позволяет мне создавать теноры вне кучи, которые я могу освободить только путем явного вызова статического метода библиотеки.Тем не менее, я хочу использовать тензоры в обязательном порядке, не беспокоясь об освобождении памяти, так же, как любой обычный объект в Java.
Единственный способ, которым я могу думать об этом, - это (неправильно) использовать сборщик мусора JVM следующим образом:
«Диспетчер памяти» отслеживает количество отключенныхпамять кучи расходуется, и при достижении порога вызывается System.gc()
.
object MemoryManager {
val Threshold: Long = 2L * 1024L * 1024L * 1024L // 2 GB
val FloatSize = 4
private val hiMemMark = new AtomicLong(0)
def dec(size: Long): Long = hiMemMark.addAndGet(-size * FloatSize)
def inc(size: Long): Long = hiMemMark.addAndGet(size * FloatSize)
def memCheck(size: Long): Unit = {
val level = inc(size)
if (level > Threshold) {
System.gc()
}
}
}
Сами тензоры обернуты в класс с помощью метода finalize, который освобождает память вне кучи, например:
class Tensor private (val payload: SWIGTYPE_p_THFloatTensor) {
def numel: Int = TH.THFloatTensor_numel(payload)
override def finalize(): Unit = {
val memSize = MemoryManager.dec(numel)
TH.THFloatTensor_free(payload)
}
}
Создание тензора выполняется фабрикойметод, который уведомляет менеджер памяти.Например, чтобы создать тензор нулей:
object Tensor {
def zeros(shape: List[Int]): Tensor = {
MemoryManager.memCheck(shape.product)
val storage = ... // boilerplate
val t = TH.THFloatTensor_new
TH.THFloatTensor_zeros(t, storage)
new Tensor(t)
}
}
Я понимаю, что это наивный подход, но можно ли мне с этим сойти?Кажется, что он работает нормально, даже при параллельной работе (которая генерирует множество лишних вызовов на System.gc()
, но в противном случае ничего) Или вы можете придумать лучшее решение?
Спасибо.