为什么Frame.ofRecords在喂入由并行计算生成的序列时会出现结果?
我正在运行一些计算一系列记录的代码,并以该序列作为参数调用Frame.ofRecords
。记录的计算使用PSeq.map
从库FSharp.Collections.ParallelSeq
。为什么Frame.ofRecords在喂入由并行计算生成的序列时会出现结果?
如果我将序列转换为列表,那么输出结果是OK。下面是代码和输出:
let summaryReport path (writeOpenPolicy: WriteOpenPolicy) (outputs: Output seq) =
let foo (output: Output) =
let temp =
{ Name = output.Name
Strategy = string output.Strategy
SharpeRatio = (fst output.PandLStats).SharpeRatio
CalmarRatio = (fst output.PandLStats).CalmarRatio }
printfn "************************************* %A" temp
temp
outputs
|> Seq.map foo
|> List.ofSeq // this is the line that makes a difference
|> Frame.ofRecords
|> frameToCsv path writeOpenPolicy ["Name"] "Summary_Statistics"
Name Name Strategy SharpeRatio CalmarRatio
0 Singleton_AAPL MyStrategy 0.317372564 0.103940018
1 Singleton_MSFT MyStrategy 0.372516931 0.130150478
2 Singleton_IBM MyStrategy Infinity
的printfn
命令让我通过在每种情况下所述可变temp
被正确地计算检查校验。 最后一行代码只是FrameExtensions.SaveCsv
的包装。
如果我删除|> List.ofSeq
行,然后出来的东西是乱码:
Name Name Strategy SharpeRatio CalmarRatio
0 Singleton_IBM MyStrategy 0.317372564 0.130150478
1 Singleton_MSFT MyStrategy 0.103940018
2 Singleton_AAPL MyStrategy 0.372516931 Infinity
注意,现在空(对应于NaN
)和Infinity
项目在不同的线路和其他东西也混了。
这是怎么发生的?
Frame.ofRecords
函数迭代遍历序列多次,所以如果您的序列在重复调用时返回不同的数据,则会在帧中获得不一致的数据。
下面是一个小例子:
let mutable n = 0.
let nums = seq { for i in 0 .. 10 do n <- n + 1.; yield n, n }
Frame.ofRecords nums
这将返回:
Item1 Item2
0 -> 1 12
1 -> 2 13
2 -> 3 14
3 -> 4 15
4 -> 5 16
5 -> 6 17
6 -> 7 18
7 -> 8 19
8 -> 9 20
9 -> 10 21
10 -> 11 22
正如你可以看到,该序列的第一次迭代过程中获得的第一项,第二项是在第二次迭代期间获得。
这应该可以更好地记录下来,但它在一般情况下会使性能更好 - 如果您可以将PR发送到文档,那将会很有用。
并行序列以任意顺序运行,因为它们在多个处理器之间分裂,因此结果集将以随机顺序排列。您可以随时对它们进行排序,或不平行运行数据。
我不认为问题在于序列失灵。正如我观察到的那样,问题并不在于线路发生故障。这不会是一个问题。问题是这些数字是垂直打乱的。例如,在第一个表的第一行中,可以看到数字0.317372564和0.130150478。这种数字组合不会出现在第二个表格的三行中的任何一行中。如果发生的所有事情都是项目未排序,那么这个数字组合将不得不出现的是第二个表格的三行之一。 – Soldalma
谢谢。你能否给我一个关于如何将公关发送给文档的提示? – Soldalma
@Soldalma - 文档位于https://github.com/BlueMountainCapital/Deedle存储库中。如果您已经为其他Github项目完成了PR,那应该是您开始创建所需的一切。 – rmunn
@rmunn - 我看着它,我不适合做PR。害怕我可能会损坏某些东西。在任何情况下,我所能想到的就是在“Frame.ofRecords”处理它之前将序列转换为列表。其他任何选择都会非常复杂,可能也很慢。 – Soldalma