2010-12-19 76 views
12

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

我的意思是整数类型是一个类型定义通常的操作符(/ * +等)和行为像一个整数,内部表示并不重要。

用桌子做这样的事情很简单,问题是,我尝试过,而且表现非常差(当然)。这是我的部分实现:

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 

我收集的主要性能损失是(当然)非常多的分配。 LuaJit能够很好地优化运算符功能,但不能实现metatables分配。

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

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

编辑:我会在这里添加额外的信息,以便一切仍是集中

@Mud:我需要,在一定程度上有透明混合算术中你在Python具有相同的方式/ ruby​​ /等,但是可能具有最佳性能。我使用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 

我能达到这个到某一点,与实施上述表现。问题在于,我对每个数字的运算速度都很慢,因为常规数字也被装箱。我可以超载与调试LIB号的元表,但

  • 我不知道这个功能如何可靠的是在生产高质量的软件使用
  • 它将数字以来的表现还是慢下来,能够有一个统一的数字接口,我将不得不使用(数字):get(),这将在任何情况下减缓操作。

我在昨晚的C中推出了自己的Integer实现。问题是,虽然它比普通的lua中我的天真实现有所改进,并且还改进了对math.floor的内联调用,但使用LuaJIT时的情况并不那么明显,在这种情况下,内联调用仍然是比C更快的批次实现。

另一种解决方案是始终使用unboxed数字,并在我的编译器中使用某种类型的传播来跟踪整数,并在需要时使用适当的内联操作,但此解决方案的复杂性要大得多,击败了使用Lua/LuaJIT作为后端的全部目的。

我会尝试你的实现,但我怀疑它会比在LuaJIT中的内联调用更好。很可能,我所拍摄的内容(既有双精度和整数的透明操作,又有接近对luaJIT的内联调用的性能)显然是不可能的。非常感谢您的帮助。

@miky:谢谢,这看起来不错,但我怀疑我可以用它补丁luaJIT,如果我不能,它会为我的目标放松所有的Interrest。

+2

是的,这是真的,想用什么来修补LuaJIT是疯狂,它始终是更好地实现纯Lua的整个事情(当然,这就是Lua是很好的,它提供的工具.. )。然后LuaJIT将能够优化它(而不是C函数)。 – 2010-12-21 16:21:23

回答

4

如果你想只有处理整数,你总是可以#define LUA_NUMBER intluaconf.h

14

为什么你需要它们吗?帮助您找到解决问题性能的最佳方法是了解问题。你需要什么特别的整数?

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

那么,你正在为每个操作创建闭包,而且我不明白为什么你有一个Double类,因为Lua的数字类型已经是double类型了。你不能做这样的事吗?

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 

有人认为这将有可能与一个自定义的C实现和用户数据做的更好?

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

编辑:我写了一个test C implementation,它比本文中介绍的Lua实现快了约5倍。

+0

嘿泥,谢谢你的回答,我回答了原始问题 – 2010-12-20 13:04:10

+1

我接受了你的回答,因为即使它最终没有解决我的问题,它*也回答了这个问题。虽然luaJIT在使用C库时回退到解释器,但最终使用C库并不是一个好的解决方案。 – 2010-12-21 16:14:06

1

你可以尝试LNUM补丁,它修改Lua核心以添加整数数字类型,比如32和64位整数以及双精度。它也支持复数。

+0

自述:“使用补丁不会以任何方式改变Lua的外部行为”。所以绝对不是我所追求的 – 2010-12-21 16:01:44