2016-03-04 63 views
2

我的程序需要内存,所以我需要尽可能多地保存内存。 将整数值赋给变量时,值的类型始终为Int64,无论是0还是+ 2^63-1或-2^63。 我无法找到一个巧妙的方法来有效地分配内存,所以我写了,看起来像这样(在本例中为整数)的函数:朱莉娅:高效的内存分配

function right_int(n) 
    types = [Int8,Int16,Int32, Int64, Int128] 
    for t in reverse(types) 
     try 
      n = t(n) 
     catch InexactError 
      break 
     end 
    end 
    n 
end 

a = right_int(parse(Int,eval(readline(STDIN)))) 

但我不认为这是一个好办法做到这一点。

我也有一个相关的问题:什么是有效的数字操作方式,而不用担心typemins和typemaxs?将每个操作数转换为BigInt,然后应用right_int?

回答

8

你错过了树木的森林。 right_int类型不稳定。类型稳定性是减少分配和快速制作Julia的关键概念。通过尝试“正确调整”整数以节省空间,实际上会导致更多的分配和更高的内存使用量。作为一个简单的例子,我们试着从1-100开始制作一个“正确大小”的100个整数数组。他们都足够小,以适应Int8,所以这只是100个字节加上数组头,对吧?

julia> @allocated [right_int(i) for i=1:100] 
26496 

哇,26,496字节!为什么没有工作?为什么有这么多的开销?关键是,朱莉娅不能推断出的right_int的类型可能是,所以它必须支持返回任何类型:

julia> typeof([right_int(i) for i=1:100]) 
Array{Any,1} 

这意味着朱莉娅不能打包整数密集成阵,和而是将它们表示为指向100个单独“盒装”整数的指针。这些框告诉Julia如何解释它们包含的数据,这需要相当多的开销。这不仅会影响数组,任何时候在任何函数中使用right_int的结果时,Julia都不能再优化该函数并最终进行大量分配。我高度建议您阅读更多关于this very good blog postmanual's performance tips中的类型稳定性。

至于要使用哪种整数类型:只要使用Int,除非你知道你会超过20亿。在您知道需要支持大数字的情况下,请使用BigInt。这是值得注意的是,创建一个类似的BigInt阵列使用显著较少的内存比上面的“大小合适的”阵列:

julia> @allocated [big(i) for i=1:100] 
6496 
+0

所以,如果我不知道,如果用户将输入整数或bigints我应该保存一切都如同BigInt? – Pigna

+0

取决于你的用例。他们是否真的需要超过20亿的数字?我的观点是,如果你的Julia程序受内存限制,你应该在检查你的热循环中的类型稳定性之前,试着用'right_int'之类的方法来保存少量的字节。 –

+0

他们不太可能会输入大于20亿的数字,但仍然可能发生的事情是我以后需要做的操作将超出限制。但无论如何,我明白了,谢谢@MattB。 – Pigna