【问题标题】:F# Array.Parallel hangingF# Array.Parallel 挂起
【发布时间】: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 中的任意代码。

标签: f# parallel-processing


【解决方案1】:

更新情况以及我如何解决此问题。

由于我公司的防火墙政策,我无法从我的示例中上传代码,所以最后我的问题没有足够的细节。我没有提到我正在使用类型提供程序,这在这种情况下是重要的信息。但这是我想出来的。

我正在为 SQL Server 使用 F# 类型提供程序,并且正在传递我怀疑不是线程安全的服务类型。当我用普通的旧 F# 记录替换 ServiceTypes 时,代码运行良好 - 不再出现死锁,一切都完成且没有错误。

【讨论】: