我是Lua的新手(将其用于Torch7框架)。我有一个输入功能文件,大小约为1.4GB(文本文件)。简单的io.open函数在尝试打开此文件时抛出错误“内存不足”。在浏览用户组和文档时,我发现它的可能是一个Lua限制。这有解决方法吗?或者我在阅读文件时做错了什么?
local function parse_file(path)
-- read file
local file = assert(io.open(path,"r"))
local content = file:read("*all")
file:close()
-- split on start/end tags.
local sections = string.split(content, start_tag)
for j=1,#sections do
sections[j] = string.split(sections[j],'\n')
-- remove the end_tag
table.remove(sections[j], #sections[j])
end
return sections
end
local train_data = parse_file(file_loc .. '/' .. train_file)
编辑:我想要阅读的输入文件包含我想训练模型的图像功能。这个文件是有序的({start-tag} ... contents ... {end-tag} {start-tag} ...等等...),所以如果我可以加载这些文件就可以了部分(开始标记到结束标记)一次一个。但是,我希望将所有这些部分加载到内存中。
答案 0 :(得分:2)
事实证明,加载大文件问题的最简单方法是将Torch升级到Lua5.2或更高版本!正如Torch的开发人员对torch7-google-group所做的那样。
cd ~/torch
./clean.sh
TORCH_LUA_VERSION=LUA52 ./install.sh
从5.2版开始,内存限制不存在!我测试了这个,它工作得很好!
参考:https://groups.google.com/forum/#!topic/torch7/fi8a0RTPvDo
另一种可能的解决方案(更优雅,类似于@Adam在他的回答中建议的)是使用逐行读取文件并使用张量或tds来存储数据,因为它使用了以外的内存Luajit。由于Vislab,代码示例如下所示。
local ffi = require 'ffi'
-- this function loads a file line by line to avoid having memory issues
local function load_file_to_tensor(path)
-- intialize tensor for the file
local file_tensor = torch.CharTensor()
-- Now we must determine the maximum size of the tensor in order to allocate it into memory.
-- This is necessary to allocate the tensor in one sweep, where collumns correspond to letters and rows correspond to lines in the text file.
--[[ get number of rows/collumns ]]
local file = io.open(path, 'r') -- open file
local max_line_size = 0
local number_of_lines = 0
for line in file:lines() do
-- get maximum line size
max_line_size = math.max(max_line_size, #line +1) -- the +1 is important to correctly fetch data
-- increment the number of lines counter
number_of_lines = number_of_lines +1
end
file:close() --close file
-- Now that we have the maximum size of the vector, we just have to allocat memory for it (as long there is enough memory in ram)
file_tensor = file_tensor:resize(number_of_lines, max_line_size):fill(0)
local f_data = file_tensor:data()
-- The only thing left to do is to fetch data into the tensor.
-- Lets open the file again and fill the tensor using ffi
local file = io.open(path, 'r') -- open file
for line in file:lines() do
-- copy data into the tensor line by line
ffi.copy(f_data, line)
f_data = f_data + max_line_size
end
file:close() --close file
return file_tensor
end
从张量读取数据简单快捷。例如,如果您想要读取文件中的第10行(将在张量的第10个位置),您可以简单地执行以下操作:
local line_string = ffi.string(file_tensor[10]:data()) -- this will convert into a string var
警告:这将在内存中占用更多空间,并且对于某些行比另一行更长的情况可能不是最佳的。但是如果你没有内存问题,甚至可以忽略这一点,因为当将文件中的张量加载到内存中时,速度非常快,并且可能会在此过程中为您节省一些白发。
参考:https://groups.google.com/forum/#!topic/torch7/fi8a0RTPvDo
答案 1 :(得分:0)
我从来没有需要读取如此大的文件,但如果你的内存不足,你可能需要逐行阅读。经过一些快速研究后,我从lua网站上找到了这个:
buff = buff..line.."\n"
buff是一个包含50,020字节的新字符串,而现在的旧字符串是>垃圾。在两个循环周期之后,buff是一个50,040字节的字符串,并且有两个旧字符串总共产生超过100千字节的垃圾。因此,Lua非常正确地决定,它是运行垃圾收集器的好时机,因此它可以释放那些100 KB。问题是这将每两个周期发生一次,因此Lua将在完成循环之前运行其垃圾收集器两千次。即使完成所有这些工作,其内存使用量也将是文件大小的三倍。更糟糕的是,每个连接必须将整个字符串内容(50千字节和增长)复制到新字符串中。
所以看起来加载大文件会使用疯狂的内存量,即使你逐行读取它并且每次都使用连接:
local buff = "" while 1 do local line = read() if line == nil then break end buff = buff..line.."\n" end
然后他们提出了更多的记忆保存过程:
function newBuffer () return {n=0} -- 'n' counts number of elements in the stack end function addString (stack, s) table.insert(stack, s) -- push 's' into the top of the stack for i=stack.n-1, 1, -1 do if string.len(stack[i]) > string.len(stack[i+1]) then break end stack[i] = stack[i]..table.remove(stack) end end function toString (stack) for i=stack.n-1, 1, -1 do stack[i] = stack[i]..table.remove(stack) end return stack[1] end
这比以前占用更少的内存。所有信息来自:
http://www.lua.org/notes/ltn009.html
希望有所帮助。