我做了一些有机化学模型。模型由生成的ModelData.fs文件描述,例如:https://github.com/kkkmail/ClmFSharp/blob/master/Clm/Model/ModelData.fs。该文件的结构非常简单,使用生成的模型文件是它可能工作的唯一方法。
所引用的文件仅用于测试,但真正的模型是巨大的,可能接近60-70MB/150万LOC。当我试图编译这样的文件时,F#编译器fsc.exe就会挂断,再也不会回来了。它“吃掉”大约1.5GB的内存,然后在几乎100%的处理能力下永远做一些事情。它可以很清楚地处理较小的型号,大约需要10 MB在一分钟之内。因此,在fsc中,在10 MB到70 MB之间的某个地方会出现严重故障。
我想知道是否可以对fsc编译项目的方式进行一些参数调整,以使其能够处理如此庞大的模型。
我所指的大型模型有一个参数集如下:let numberOfSubstances = 65643。这将产生大小相同的各种数组。我想知道这是否是问题的根源。
非常感谢!
发布于 2019-02-04 14:50:03
我不认为你需要自动生成所有这些。
从您的评论中,我了解到函数d0,d1,.是从一个大的稀疏矩阵中生成的,它可以将所有的输入数组x (用系数)加起来,但关键是跳过零系数的求和,这给了你很大的性能增益,因为这个矩阵是巨大的。这是正确的评估吗?
如果是这样的话,我仍然不认为您需要生成代码来做到这一点。
让我们来看看。我将假设您的巨型稀疏矩阵有一个获取单元值的接口,它看起来如下所示:
let getMatrixCell (i: int) (j: int) : double
let maxI: int
let maxJ: int那么您的自动生成代码可能如下所示:
let generateDFunction (i: int) =
printfn "let d%d (x: double[]) =" i
printfn " [|"
for j in 0..maxJ do
let cell = getMatrixCell i j
if cell <> 0 then
printfn " %f * x.[%d]" cell j
printfn " |]"
printfn " |> Array.sum"这会导致这样的结果:
let d25 (x : array<double>) =
[|
-1.0 * x.[25]
1.0 * x.[3]
|]
|> Array.sum注意,我在这里简化了:在您的示例文件中,函数看起来也是由x.[i]乘以负系数。但也许我也太复杂了,因为看起来所有的系数都是1或-1。但这对我来说并不重要。
现在,在注释中,有人建议您不要生成函数d0,d1,.而是直接与矩阵一起工作。例如,这将是对这种建议的天真实施:
let calculateDFunction (i: int) (x: double[]) =
[| for j in 0..maxJ -> (getMatrixCell i j) * x.[j] |] |> Array.sum然后,您认为这个解决方案会慢得令人望而却步,因为它总是迭代整个数组的x,这是很大的,但是大部分系数都是零,所以它不必这样做。
然后,解决这个问题的方法是使用生成代码的中间步骤:生成只涉及非零指标的函数,然后编译和使用这些函数。
但是重点是:是的,你确实需要一个中间的步骤来消除非零指标,但是它不需要生成和编译代码!
相反,您可以提前准备非零指标的列表/数组:
let indicies =
[| for i in 0..maxI ->
[ for j in 0..maxJ do
let cell = getMatrixCell i j
if cell <> 0 then yield (j, cell)
]
|]这将产生一个数组indicies : Array<int list>,其中每个索引k对应于您的自生成函数dk,它包含一个非零矩阵的列表以及它们在矩阵中的值。例如,上面给出的函数d22将由indicies的第22元素表示。
indicies.[22] = [ (25, -1.0), (3, 1.0) ]根据这个中间结构,您可以计算任意函数dk。
let calculateDFunction (k: int) (x: double[]) =
[| for (j, coeff) in indicies.[k] -> coeff * x.[j] |] |> Array.sum事实上,如果性能对您至关重要(从注释中可以看出),那么您可能应该取消所有这些中间数组:在每次迭代中分配数百或数千个堆绝对没有帮助。您可以用可变变量和:
let calculateDFunction (k: int) (x: double[]) =
let sum = 0.0
for (j, coeff) in indicies.[k] do
sum <- sum + coeff * x.[j]
sumhttps://stackoverflow.com/questions/54506429
复制相似问题