2017-08-28 4 views
2

Je cours un peu de code qui calcule une séquence d'enregistrements et appelle Frame.ofRecords avec cette séquence comme argument. Les enregistrements sont calculés en utilisant PSeq.map à partir de la bibliothèque FSharp.Collections.ParallelSeq.Pourquoi Frame.ofRecords brouille-t-il ses résultats lorsqu'il reçoit une séquence générée par un calcul parallèle?

Si je convertis la séquence en liste, la sortie est OK. Voici le code et la sortie:

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 

La commande printfn me laisser vérifier par des inspections que dans chaque cas a été calculé correctement la temp variable. La dernière ligne de code est juste une enveloppe autour de FrameExtensions.SaveCsv.

Si je supprime la ligne |> List.ofSeq alors ce qui sort est brouillée:

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 

Notez que le vide (correspondant à NaN) et Infinity articles sont maintenant dans les différentes lignes et d'autres choses sont également mélangés.

Pourquoi cela se produit-il?

Répondre

3

La fonction Frame.ofRecords effectue une itération sur la séquence plusieurs fois. Par conséquent, si votre séquence renvoie des données différentes lorsqu'elle est appelée de manière répétée, vous obtenez des données incohérentes dans la trame.

Voici un exemple minimal:

let mutable n = 0. 
let nums = seq { for i in 0 .. 10 do n <- n + 1.; yield n, n } 

Frame.ofRecords nums 

Ce retour:

 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  

Comme vous pouvez le voir, le premier élément est obtenu lors de la première itération de la séquence, tandis que le second éléments est obtenu lors de la deuxième itération.

Cela devrait probablement être mieux documenté, mais il rend la performance meilleure dans des scénarios typiques - si vous pouvez envoyer un PR aux docs, ce serait utile.

+0

Merci. Pourriez-vous me donner un indice sur la façon d'envoyer un PR aux docs? – Soldalma

+0

@Soldalma - Les documents se trouvent dans le dépôt https://github.com/BlueMountainCapital/Deedle. Si vous avez fait des PR pour d'autres projets Github, cela devrait être tout ce dont vous avez besoin pour commencer. – rmunn

+0

@rmunn - J'ai regardé dedans et je ne suis pas à l'aise de faire un PR. J'ai peur que je puisse endommager quelque chose. En tout cas, tout ce que je peux penser à faire est de convertir la séquence en une liste avant que 'Frame.ofRecords' la traite. Toute autre alternative serait assez compliquée et probablement très lente. – Soldalma

1

Les séquences parallèles sont exécutées dans un ordre arbitraire, car elles sont réparties sur de nombreux processeurs. Par conséquent, le jeu de résultats sera dans un ordre aléatoire. Vous pouvez toujours les trier par la suite, ou ne pas exécuter vos données en parallèle.

+0

Je ne pense pas que le problème est que la séquence est tombée en panne. Comme je l'ai observé, le problème n'était pas que les lignes étaient hors service. Ce ne serait pas un problème. Le problème est que les chiffres se sont brouillés verticalement. Par exemple, dans la première rangée du premier tableau on voit les nombres 0.317372564 et 0.130150478. Cette combinaison de nombres n'apparaît dans aucune des trois lignes de la seconde table. Si tout ce qui se passait était que les éléments n'étaient pas triés, cette combinaison de nombres devrait apparaître est l'une des trois rangées de la deuxième table. – Soldalma