如何在 Linux 上绕过 64 位 LuaJIT 的 1GB 内存限制?
概述是我正在开发原型代码以了解我的问题空间,并遇到“PANIC:unprotected error in call to Lua API(not enough memory)”错误。我正在寻找绕过此限制的方法。
环境底线是Torch,这是一个在LuaJIT上运行的科学计算框架,而LuaJIT又运行在Lua上。我需要Torch,因为我最终想要使用GPU上的神经网络来解决我的问题,但为了到达那里,我需要一个良好的问题表示来提供给神经网络。我停留在Centos Linux上,并且我怀疑尝试从源代码重建所有的32位模式(据说这会将LuaJIT内存限制扩展到4GB)将是一场噩梦(如果可以的话),因为所有的库都需要这样做。
问题空间本身可能不是特别相关,但在概述中,我有计算距离并将这些距离“分组”(即制作直方图),以尝试确定最有用的范围的点的数据文件。方便的是,我可以创建各种不同的bin和torch.save()混乱的计数表,然后稍后拾起并使用不同的归一化等检查,因此经过一个月的尝试,我发现这非常简单和强大。
我可以在每个具有15个bin的3个距离的情况下使其工作(15x15x15加开销),但这只是通过添加显式的garbagecollection()调用并使用fork()/wait()来实现的。每个数据文件,以便外循环将继续运行,即使其中一个数据文件(其中有几千个)仍然超出内存限制并使子项崩溃。随着每个成功的子进程现在必须读取,修改和写入当前的二进制计数集,这变得更加痛苦-我的适用于此的最大文件目前为36mb。我想要更大(更多的bin),而且真的希望只将计数保存在我无法访问的15个gigs的RAM中。
因此,这是我考虑过的一些路径;如果您可以确认/否认这些路径中的任何一条会/不会将我带出1gb界限,或只会在它内部提高我的效率,请务必发表评论。如果您可以提出我没有考虑的另一个方法,请务必发表评论。
我是否错过了启动可以从中读取任意表格的Lua进程的方法?毫无疑问,我可以把我的问题分成更小的部分,但解析从上下文返回表格(如从调用到另一个Lua脚本的系统调用)似乎容易出错,并且写入/读取小的中间文件将会是大量的磁盘I / O。
我是否错过了在高内存中存储并访问表格的模块?这似乎是我真正想要的,但仍未找到
是否可以将FFI C数据结构放在1GB之外?似乎这不可能是情况,但我确实缺乏对首先导致限制的真实理解。我怀疑这只会为一些已经超出原型阶段的部分提供比通用Lua表更高的效率?(除非我为每个更改编写了一堆代码)
当然,我可以通过使用C编写扩展(Torch似乎支持应该超出限制的网络),但我的简短调查引用了“lightuserdata”指针--是否意味着更常规的扩展也不会超出1GB?为了这应该是一个原型练习的事情,这也似乎具有重大的开发成本。
我很了解C,所以使用FFI或扩展路径并不困扰我-但是,我从经验中知道,在这种方式中封装算法既可以是非常优美的,也可以是非常痛苦的,因为有两个地方可以隐藏错误。在栈中处理包含表中表的数据结构似乎也不是很好。在我做出这种努力之前,我想确定最终结果是否真的会解决我的问题。
感谢阅读长篇文章。
以下是那些在未来发现此问题的人的跟进信息:
关键信息如Colonel Thirty Two所发表的,即C模块扩展和FFI代码很容易超出限制。(而引用的Lua列表帖子也提醒了超出限制的纯Lua表将非常缓慢地回收)
我花了一些时间来整合访问和保存/加载我的对象,所以在这里:
我使用lds作为起点,在https://github.com/neomantra/lds上使用了特别是1-D数组代码。
这使得使用torch.save()时出现了问题,因为它不知道如何编写新对象。对于每个对象,我添加了以下代码(以Array为例):
function Array:load(inp)
for i=1,#inp do
self._data[i-1] = tonumber(inp[i])
end
return self
end
function Array:serialize ()
local siz = tonumber(self._size)
io.write(' lds.ArrayT( ffi.typeof("double"), lds.MallocAllocator )( ', siz , "):load({")
for i=0,siz-1 do
io.write(string.format("%a,", self._data[i]))
end
io.write("})")
end
请注意,我的应用程序特定使用双精度和malloc(),因此更好的实现将存储和在self中使用这些值,而不是像上面那样硬编码。
然后,如在PiL和其他地方讨论的那样,我需要一个可以处理对象的序列化程序:
function serialize (o)
if type(o) == "number" then
io.write(o)
elseif type(o) == "string" then
io.write(string.format("%q", o))
elseif type(o) == "table" then
io.write("{\n")
for k,v in pairs(o) do
io.write(" ["); serialize(k); io.write("] = ")
serialize(v)
io.write(",\n")
end
io.write("}\n")
elseif o.serialize then
o:serialize()
else
error("cannot serialize a " .. type(o))
end
end
这需要用以下内容进行包装:
io.write('do local _ = ')
serialize( myWeirdTable )
io.write('; return _; end')
然后,可以使用以下内容重新加载该输出
local myWeirdTableReloaded = dofile('myWeirdTableSaveFile')
有关dofile(),请参见PiL(Lua编程书)
希望这能帮助到某人!
你可以使用 torch tds 模块。在 README 中,它描述道:
这些数据结构不依赖 Lua 的内存分配器,也不受 Lua 垃圾回收器的限制。
仅支持 C 类型的存储:当前支持的类型有数字、字符串、数据结构本身(参见嵌套:例如可以在哈希中包含哈希或向量),以及 torch 张量和存储。所有数据结构都可以存储异构对象,并支持 torch 序列化。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
只有由LuaJIT本身分配的对象才被限制为2GB内存。这意味着,表、字符串、完全的userdata(即非lightuserdata)和使用
ffi.new分配的FFI对象将计入限制,但是使用malloc、mmap等分配的对象不受此限制(无论是由C模块还是FFI调用)。分配结构体示例使用
malloc:ffi.cdef[[ typedef struct { int bar; } foo; void* malloc(size_t); void free(void*); ]] local foo_t = ffi.typeof("foo") local foo_p = ffi.typeof("foo*") function alloc_foo() local obj = ffi.C.malloc(ffi.sizeof(foo_t)) return ffi.cast(foo_p, obj) end function free_foo(obj) ffi.C.free(obj) end据我所知,LuaJIT 3.0中要实现的新GC不会有这个限制,但我最近没有听到任何关于它的开发的消息。
来源:http://lua-users.org/lists/lua-l/2012-04/msg00729.html