我注意到在Julia中使用匿名函数的性能损失。为了说明我有两个quicksort的实现(从Julia分布的微观性能基准中获得)。所述第一按升序排序在Julia中使用匿名函数的性能损失
function qsort!(a,lo,hi)
i, j = lo, hi
while i < hi
pivot = a[(lo+hi)>>>1]
while i <= j
while a[i] < pivot; i += 1; end
while pivot < a[j]; j -= 1; end
if i <= j
a[i], a[j] = a[j], a[i]
i, j = i+1, j-1
end
end
if lo < j; qsort!(a,lo,j); end
lo, j = i, hi
end
return a
end
第二需要一个附加的参数:可用于指定升序或降序排序,或比较用于更特殊的类型
function qsort_generic!(a,lo,hi,op=(x,y)->x<y)
i, j = lo, hi
while i < hi
pivot = a[(lo+hi)>>>1]
while i <= j
while op(a[i], pivot); i += 1; end
while op(pivot, a[j]); j -= 1; end
if i <= j
a[i], a[j] = a[j], a[i]
i, j = i+1, j-1
end
end
if lo < j; qsort_generic!(a,lo,j,op); end
lo, j = i, hi
end
return a
end
有一个匿名函数当对Int64的数组进行排序时,性能会受到严重影响,默认版本的速度要快一个数量级。下面是时间(秒)排序的长度N数组:
N qsort_generic qsort
2048 0.00125 0.00018
4096 0.00278 0.00029
8192 0.00615 0.00061
16384 0.01184 0.00119
32768 0.04482 0.00247
65536 0.07773 0.00490
的问题是:这是由于将在时间待熨烫出在编译器的限制,或是否有传递函子的惯用方式/应该在这种情况下使用的匿名函数?
更新从答案看来,这是一种将在编译器中解决的问题。
与此同时,有两个建议的解决方法。这两种方法都相当简单,尽管它们开始感觉像是你必须在C++中使用的那种jiggery-pokery(尽管它们的规模并不那么尴尬)。
第一个是由@Toivo Henningsson建议的FastAnon软件包。我没有尝试这种方法,但看起来不错。
我试用了@simonstar建议的第二种方法,它给了我与非通用qsort相当的性能!执行:
abstract OrderingOp
immutable AscendingOp<:OrderingOp end
immutable DescendingOp<:OrderingOp end
evaluate(::AscendingOp, x, y) = x<y
evaluate(::DescendingOp, x, y) = x>y
function qsort_generic!(a,lo,hi,op=AscendingOp())
i, j = lo, hi
while i < hi
pivot = a[(lo+hi)>>>1]
while i <= j
while evaluate(op, a[i], pivot); i += 1; end
while evaluate(op, pivot, a[j]); j -= 1; end
if i <= j
a[i], a[j] = a[j], a[i]
i, j = i+1, j-1
end
end
if lo < j; qsort_generic!(a,lo,j,op); end
lo, j = i, hi
end
return a
end
谢谢大家的帮助。
看起来像一个非常简单的答案OP的问题给我。当然,这看起来不是对问题的批评,也不是要求澄清。 – 2014-10-03 12:29:50
谢谢Stefan。很高兴知道,没有任何理由这样的匿名函数不能很快采用“小技巧”。 – bcumming 2014-10-04 10:18:53