Lua整数类型

rap*_*ard 14 lua integer

我真的需要在Lua中有一个整数类型.

我所说的整数类型是一个定义通常运算符(/*+ etc)的类型,其行为类似于整数,内部表示无关紧要.

用表做这样的事情非常简单,问题是,我试过,而且性能非常差(当然).这是我的部分实现:

function num_op(a, b, calc_func)
    local atype = pytype(a)
    local btype = pytype(b)
    local a_val, b_val

    a_val = (atype == "Integer" or atype == "Double") and a[1] or a
    b_val = (btype == "Integer" or btype == "Double") and b[1] or b
    val = calc_func(a_val, b_val)

    if atype == "Integer" and btype == "Integer" then
        return Integer:create(val)
    else
        return Double:create(val)
    end
end

numeric_mt = { 
    __add = function(a, b)
        return num_op(a, b, function(a,b) return a + b end)
    end,

    __sub = function(a, b)
        return num_op(a, b, function(a,b) return a - b end)
    end,

    __div = function(a, b)
        return num_op(a, b, function(a,b) return a / b end)
    end,

    __mul = function(a, b)
        return num_op(a, b, function(a,b) return a * b end)
    end,

    __tostring = function(a)
        return tostring(a[1])
    end
}

-----------------------------
-- Integer type definition --
-----------------------------

Integer = {}
Integer_mt = table.copy(numeric_mt)
Integer_mt["__index"] = Integer

function Integer:create(value)
    local new_inst = {math.floor(value)}
    setmetatable(new_inst, Integer_mt)
    return new_inst
end

function Integer:className()
    return "Integer"
end
Run Code Online (Sandbox Code Playgroud)

我收集的主要性能损失是(当然)非常多的分配.LuaJit能够很好地优化运算符函数,但不能优化元表分配.

有人认为使用自定义c实现和userdata可以做得更好吗?或者是我追求的不可能实现的目标?

注意:我知道 lua没有整数.我也知道我可以使用数学库获得相同的结果.我想要的是使用整数时的完全透明度,除了创建阶段.

编辑:我将在这里添加其他信息,以便所有内容仍然集中

@Mud:我需要在某种程度上使用与python/ruby​​/etc相同的透明混合算法,但具有最佳性能.我正在使用luaJIT作为编译器的目标,使用常规Lua作为luaJIT不支持的平台的后备.这对性能特征非常重要.

这意味着我希望能够做到这一点:

a = int(5) -- Integer value
b = int(2) -- Another Integer
c = 2      -- Double
d = a / b  -- == 2 , integer arithmetics
e = a / c  -- == 2.5, floating point arithmetics
Run Code Online (Sandbox Code Playgroud)

我可以达到某一点,实现如上所示.问题是我对每个数字的操作都在减慢,因为常规数字也是盒装的.我可以使用调试库重载数字的元数据,但是

  • 我不知道这个功能在生产质量软件中有多可靠
  • 它仍然会减慢数字的性能,因为为了能够有一个统一的数字接口,我将不得不使用(数字):get(),这将在任何情况下减慢操作.

我昨晚在C中推出了自己的Integer实现.问题是,虽然它是在我经常LUA幼稚的做法有所改进,并且还和改进了内嵌调用math.floor,它使用LuaJIT,其中联调用仍然是一个当是更加不明朗很多比C实现更快.

另一种解决方案是始终使用未装箱的数字,并在我的编译器中使用某种类型的传播来跟踪整数并在需要时对它们使用适当的内联操作,但这种解决方案的复杂性要大得多,并且有点挫败整体使用Lua/LuaJIT作为后端的目的.

我会尝试你的实现,但我怀疑它会比LuaJIT中的内联调用更好.我可能正在拍摄的内容(具有双重和整数的透明操作,以及接近luaJIT的内联调用的性能)是完全不可能的.非常感谢您的帮助.

@miky:谢谢,这看起来不错,但是我怀疑我可以用它修补luaJIT,如果我不能,它会为我的目标失去所有的利益.

Mud*_*Mud 16

你为什么需要它们?帮助您找到问题的高效解决方案的最佳方法是了解问题.具体到底需要什么?

我收集的主要性能损失是(当然)非常多的分配.

好吧,你正在为每个操作创建闭包,我不明白为什么你有一个Double类,因为Lua的数字类型已经是双重的.你不能做这样的事吗?

Integer = {}
local function val(o) return type(o) == 'number' and o or o[1] end
function Integer.__add(a,b) return Integer:create(val(a) + val(b)) end
function Integer.__sub(a,b) return Integer:create(val(a) - val(b)) end
function Integer.__div(a,b) return Integer:create(val(a) / val(b)) end
function Integer.__mul(a,b) return Integer:create(val(a) * val(b)) end
function Integer:__tostring() return tostring(self[1]) end
function Integer:create(value)
   return setmetatable({math.floor(value)}, Integer)
end


-- test
a = Integer:create(15.34)
b = Integer:create(775.34433)
print((a*10/2+b-3)/3*a+b) --> 5005
Run Code Online (Sandbox Code Playgroud)

有人认为使用自定义c实现和userdata可以做得更好吗?

是的,C实现应该更快,因为您不需要为每个Integer创建一个表; 你的用户数据可能只是一个int*.这也将消除对floor呼叫的需要.

编辑:我写了一个测试C实现,它比本文中介绍的Lua实现快〜5倍.

  • 我接受了你的回答,因为即使它最终没有解决我的问题,它*确实*回答了这个问题。虽然 luaJIT 在使用 C 库时会回退到解释器,所以最终使用 C 库并不是一个好的解决方案 (2认同)

小智 6

在Lua 5.3中添加了整数(默认为64位)!

http://www.lua.org/versions.html#5.3