我正在运行一些计算记录序列的代码,并以该序列作为参数调用Frame.ofRecords
。记录使用库PSeq.map
中的FSharp.Collections.ParallelSeq
计算。
如果我将序列转换为列表,则输出正常。这是代码和输出:
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
项目现在位于不同的行中,其他内容也会混淆。
为什么会这样?
答案 0 :(得分:4)
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,那将是有用的。
答案 1 :(得分:1)
并行序列以任意顺序运行,因为它们在许多处理器中被分割,因此结果集将是随机顺序。您可以随后对它们进行排序,也可以不并行运行数据。