arrays - 为什么在 F# 中处理数组比列表更快

标签 arrays list f#

我正在检查 F# 列表和数组的性能。给定代码:

let list = [ 1.. 100000 ]
for i in 1 .. 100 do ignore ( list|>List.map(fun n -> n))

let array = [| 1.. 100000 |]
for i in 1 .. 100 do ignore ( array|>Array.map(fun n -> n))

我怀疑两者的运行时间非常相似。实际上,数组的速度要快 10 倍以上:数组需要 28 毫秒,而列表需要 346 毫秒!
这是为什么?我了解 F# 中列表的概念,并且例如将值附加到列表或获取子序列非常耗时,但在此代码中它只是迭代所有元素,因此我认为时间将非常可比。

在 Visual Studio 2012 中的 Release模式下进行测试(在 Debug模式下,数组的速度大约快 5 倍)。

最佳答案

主要区别在于数组被分配为连续的内存块 - Array.map函数知道输入数组的大小,并且可以只执行一次分配来获取结果数组的所有内存。另一方面,List.map函数需要为输入数组的每个元素单独分配一个“cons cell”。
map 的差异尤其明显。功能,因为这可以真正受益于预先分配。但是,对于较大的数据集,数组通常更快。如果您将代码更改为使用过滤(在构造过程中需要重新分配数组),那么数组版本的速度会快 2 倍:

for i in 1 .. 100 do ignore ( list|>List.filter(fun n -> n%5=1))
for i in 1 .. 100 do ignore ( array|>Array.map(fun n -> n%5=1))

使用列表还有其他好处——因为它们是不可变的,您可以安全地共享对列表的引用。此外,克隆一个列表并在前面添加一个元素非常有效(单个单元格分配),而对数组进行类似操作会非常慢(复制整个数组)。

关于arrays - 为什么在 F# 中处理数组比列表更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19519267/

相关文章:

.net - 具有长时间运行任务的 TPL Parallel.For

javascript - 如何获得两个数组之间的差异?

C字符数组打印数字而不是分配的章节

javascript - 在 Jquery 中将表单转换为关联数组

c# - 如何将 List<int> 转换为 string[]?

c - 如何将链表和函数指针作为输入

f# - F# 类型成员可以相互引用吗?

php - 如何修复php数组格式json错误

java - 为什么java中Collections的fill(),copy(),reverse(),shuffle()是这样实现的

error-handling - 代表 F# 中失败的受歧视联合的优雅解决方案