Algorithm F中nbody算法的优化#

Algorithm F中nbody算法的优化#,algorithm,optimization,f#,Algorithm,Optimization,F#,如何进一步优化此代码: let rec nCollect func = function | [] -> [] | x::xs -> let firstAndNext body (firstBody, ys) = let newFirst, z = func firstBody body newFirst, z::ys

如何进一步优化此代码:

let rec nCollect func = function
        | [] -> []
        | x::xs -> let firstAndNext body (firstBody, ys) = 
                        let newFirst, z = func firstBody body
                        newFirst, z::ys
                   let y, ys = List.foldBack firstAndNext xs (x, [])
                   y::(nCollect func ys)

此代码是nbody仿真程序的一部分。它获取每个主体,并在主体和下一个主体之间应用func函数。结果将用于下一次迭代。我用列表稍微优化了一下。问题是,输入主体的计数不到10,但nCollect被称为数百万次。例如,如果我在nCollect中使用尾部递归,结果会更糟。

我认为每种语言中90%的微观优化问题的答案都是相同的:使用数组、循环和变异


因此,我会使用数组、循环和变异,而不是
列表。折叠

我认为每种语言中90%的微观优化问题的答案都是一样的:使用数组、循环和变异

因此,我会使用数组、循环和变异,而不是
List.foldBack

一些快速注释

List.Fold
应该优于
List.FoldBack
。看看这里的代码,您可以看到FoldBack将分配一个临时数组,这可能会很慢,而fold可以快速遍历列表

您也可以尝试内联
firstAndNext

手动展开循环也会有帮助

一些快速评论

List.Fold
应该优于
List.FoldBack
。看看这里的代码,您可以看到FoldBack将分配一个临时数组,这可能会很慢,而fold可以快速遍历列表

您也可以尝试内联
firstAndNext

手动展开循环也会有所帮助

  • 使用更好的算法,如Ewald求和或快速多极方法(FMM)

  • 将列表和递归函数替换为数组和
    for
    循环

  • 对于小问题,使用自定义代码生成替换循环

  • 使用更好的算法,如Ewald求和或快速多极方法(FMM)

  • 将列表和递归函数替换为数组和
    for
    循环

  • 对于小问题,使用自定义代码生成替换循环


  • 除了尾部递归,你还尝试了什么?您是否有一个测试显示了问题?除了尾部递归,您还尝试了什么?是否有测试显示了问题?List.foldBack本质上是一个循环,但问题在于从循环体(firstBody)创建的中间数据。如果它足够聪明,可以将内存位置重新用于中间存储,那么就可以了。但是编译器会产生这样的魔力吗?@幽灵:如果很容易判断一个方法是否是纯的,那么这是可能的,但是在F中这是非常困难的。容易访问mutability.List.foldBack的问题之一是循环的本质,但问题在于从循环体(firstBody)创建的中间数据。如果它足够聪明,可以将内存位置重新用于中间存储,那么就可以了。但是编译器会产生这样的魔力吗?@幽灵:如果很容易判断一个方法是否是纯的,那么这是可能的,但是在F中这是非常困难的。易访问易变性的问题之一是内联没有帮助。奇怪的是,在我的情况下,折回运行得更快。内联没有帮助。奇怪的是,在我的情况下,折叠运行得更快。