我正在运行一个具有以下结构的代码:
network = createNetwork() -- loading a pre-trained network.
function train()
for i=1,#trainingsamples do
local ip = loadInput()
local ip_1 = someImageProcessing(ip)
local ip_2 = someImageProcessing(ip)
network:forward( ...some manipulation on ip_1,ip_2...)
network:backward()
collectgarbage('collect')
print debug.getlocal -- all local variables.
end
end我期望Collect垃圾()将释放所有由ip_1、ip_2和ip持有的内存。但是我可以看到内存没有被释放。这会导致内存泄漏。我想知道发生了什么事。有没有人能帮我理解一下集合体垃圾()的奇怪行为,并修复内存泄漏。
我真的很抱歉,我不能添加完整的代码。希望我添加的代码片段足以理解我的代码流程,我的网络训练代码非常类似于标准的CNN训练代码。
编辑:
抱歉,没有提到变量被声明为本地变量,并在示例代码片段中使用了一个变量的关键字。我现在已经编辑好了。唯一的全局变量是在列车函数外部声明的网络,我将ip_1和ip_2作为输入提供给网络。另外,我在下面添加了我的实际代码的修剪版本。
network = createNetwork()
function trainNetwork()
local parameters,gradParameters = network:getParameters()
network:training() -- set flag for dropout
local bs = 1
local lR = params.learning_rate / torch.sqrt(bs)
local optimConfig = {learningRate = params.learning_rate,
momentum = params.momentum,
learningRateDecay = params.lr_decay,
beta1 = params.optim_beta1,
beta2 = params.optim_beta2,
epsilon = params.optim_epsilon}
local nfiles = getNoofFiles('train')
local weights = torch.Tensor(params.num_classes):fill(1)
criterion = nn.ClassNLLCriterion(weights)
for ep=1,params.epochs do
IMAGE_SEQ = 1
while (IMAGE_SEQ <= nfiles) do
xlua.progress(IMAGE_SEQ, nfiles)
local input, inputd2
local color_image, depth_image2, target_image
local nextInput = loadNext('train')
color_image = nextInput.data.rgb
depth_image2 = nextInput.data.depth
target_image = nextInput.data.labels
input = network0:forward(color_image) -- process RGB
inputd2 = networkd:forward(depth_image2):squeeze() -- HHA
local input_concat = torch.cat(input,inputd2,1):squeeze() -- concat RGB, HHA
collectgarbage('collect')
target = target_image:reshape(params.imWidth*params.imHeight) -- reshape target as vector
-- create closure to evaluate f(X) and df/dX
local loss = 0
local feval = function(x)
-- get new parameters
if x ~= parameters then parameters:copy(x) end
collectgarbage()
-- reset gradients
gradParameters:zero()
-- f is the average of all criterions
-- evaluate function for complete mini batch
local output = network:forward(input_concat) -- run forward pass
local err = criterion:forward(output, target) -- compute loss
loss = loss + err
-- estimate df/dW
local df_do = criterion:backward(output, target)
network:backward(input_concat, df_do) -- update parameters
local _,predicted_labels = torch.max(output,2)
predicted_labels = torch.reshape(predicted_labels:squeeze():float(),params.imHeight,params.imWidth)
return err,gradParameters
end -- feval
pm('Training loss: '.. loss, 3)
_,current_loss = optim.adam(feval, parameters, optimConfig)
print ('epoch / current_loss ',ep,current_loss[1])
os.execute('cat /proc/$PPID/status | grep RSS')
collectgarbage('collect')
-- for memory leakage debugging
print ('locals')
for x, v in pairs(locals()) do
if type(v) == 'userdata' then
print(x, v:size())
end
end
print ('upvalues')
for x,v in pairs(upvalues()) do
if type(v) == 'userdata' then
print(x, v:size())
end
end
end -- ii
print(string.format('Loss: %.4f Epoch: %d grad-norm: %.4f',
current_loss[1], ep, torch.norm(parameters)/torch.norm(gradParameters)))
if (current_loss[1] ~= current_loss[1] or gradParameters ~= gradParameters) then
print ('nan loss or gradParams. quiting...')
abort()
end
-- some validation code here
end --epochs
print('Training completed')
end发布于 2016-10-14 08:22:42
正如@Adam在评论中所说,in_1和in_2变量继续被引用,它们的值不能被垃圾收集。即使您将它们更改为局部变量,它们也不会在此时被垃圾回收,因为定义它们的块还没有关闭。
您可以做的是在调用collectgarbage之前将in_1和in_2的值设置为nil,这将使先前分配的值不可用,并符合垃圾收集的条件。只有当没有其他变量可能存储相同的值时,这才会起作用。
发布于 2016-10-14 10:49:57
保罗上面的答案+1;但请注意“应该”这个词。几乎所有的时间你都会很好。然而,如果你的代码变得更复杂(你开始传递内存对象并处理它们),你可能会发现有时候Lua可能会决定保留内存对象的时间比预期的要长一点。但是不用担心(或者浪费时间试图找出原因),最终所有未使用的内存对象都会被Lua收集。垃圾收集器是一种复杂的算法,有时会显得有点不确定。
发布于 2016-10-14 14:42:52
您可以创建全局变量来存储值。因此,此变量将始终可用。因此,在重写这些值之前,这样的vars gc无法收集它们。只需将vars设为本地并从作用域中调用gc即可。此外,第一个GC周期可能只调用finalizer和第二个空闲内存。但对此并不确定。因此,您可以尝试调用gc两次。
function train()
do
local in = loadInput()
local in_1 = someImageProcessing(in)
local in_2 = someImageProcessing(in)
network:forward( ...some manipulation on in_1,in_2...)
network:backward()
end
collectgarbage('collect')
collectgarbage('collect')
print debug.getlocal -- all local variables.PS。 in在Lua中不是有效的变量名
https://stackoverflow.com/questions/40030968
复制相似问题