【发布时间】:2026-01-20 18:30:01
【问题描述】:
在过去的几天里,我一直在努力解决 F# 中的并行和异步构造问题,现在不知道该去哪里。我已经用 F# 编程了大约 4 个月 - 当然不是专家 - 我目前有一系列在 F# (asp.net 4.5) 中实现的计算,并且在按顺序执行时可以正常工作。我在多核服务器上运行计算,由于有数百万个输入要执行相同的计算,我希望利用并行性来加速它。
这些计算是非常并行的数据 - 基本上是对不同输入数据的精确计算。我尝试了许多不同的途径,但我不断遇到同样的问题——似乎并行循环永远不会到达输入数据集的末尾。我已经尝试过 TPL、ConcurrentQueues、Parallel.Array.map/iter 和所有相同的结果:程序开始时很好,然后在中间的某个地方(不确定)它只是挂起并且永远不会完成。为简单起见,我实际上从程序中删除了计算,我只是调用了一个打印方法,这是代码当前所在的位置:
let runParallel =
let ids = query {for c in db.CustTable do select c.id} |> Seq.take(5)
let customerInputArray= getAllObservations ids
Array.Parallel.iter(fun c -> testParallel c) customerInputArray
let key = System.Console.ReadKey()
0
几点... 我将上面的结果限制为只有 5 个,仅用于调试。实际程序不应用 Take(5)。 testParallel 方法只是一个 printfn “测试”。
customerInputArray 是一种复杂的数据类型。它是一个包含记录的列表元组。所以我很确定我的问题一定存在......但我添加了异常处理并且没有引发异常,所以不知道如何去寻找问题。
感谢任何帮助。提前致谢。
编辑:感谢您的建议...我认为这绝对是僵局。当我删除所有 printfn、sprintfn 和字符串 concat 操作时,它就完成了。 (当然,我需要那些东西。)
printfn、sprintfn 和字符串操作不是线程安全的吗?
另一个编辑:迭代总是在最后一个项目上停止。所以如果我的输入数组有 15 个项目,则处理在项目 14 上停止,或者似乎永远不会到达项目 15。然后一切都挂起。输入数组的大小无关紧要。有什么想法会导致这种情况吗?我什至切换到 Parallel.ForEach(而不是 Array.Parallel)和相同的行为。
【问题讨论】:
-
您是否尝试过暂停执行以查看什么需要花费大量时间?另外,请尝试将您的复杂数据类型替换为简单的数据类型,例如
let ids = [1;2;3;4;5] -
请调试您的程序,使用调试器或至少在代码周围添加 printfs 以查看它挂在哪里。
-
有死锁的可能吗?
-
参见上面的编辑..我认为我传递给 TextWriter 的字符串是以非线程安全的方式构造的......我正在使用 sprintf,甚至尝试了 '+' 操作。
-
我会说
printfn绝对不是线程安全的——你无法防止%A or %O中的任意代码。