Странное поведение в параллельной последовательности F # - PullRequest
2 голосов
/ 02 октября 2011

Я написал следующий код для генерации всех возможных комбинаций некоторых чисел:

let allCombinations (counts:int[]) = 
   let currentPositions = Array.create (counts.Length) 0     
   let idx = ref (counts.Length-1) 
   seq{
       while currentPositions.[0]<counts.[0] do                        
           yield currentPositions           
           currentPositions.[!idx]<-currentPositions.[!idx]+1         
           while currentPositions.[!idx] >= counts.[!idx] && !idx>=1 do
               currentPositions.[!idx]<-0
               idx:=!idx-1
               currentPositions.[!idx]<-currentPositions.[!idx]+1               
           idx:=counts.Length-1            
   } 

Я использую последовательность в какой-то другой части программы, например:

allCombinations counts |> Seq.map (fun idx -> buildGuess n digitsPerPos idx) ...

Все идет нормально.Программа работает как положено и генерирует комбинации.Для входа [| 2; 2; 2 |] он генерирует восемь значений:

 [|0; 0; 0|]
 [|0; 0; 1|]
 [|0; 1; 0|]
 [|0; 1; 1|]
 [|1; 0; 0|]
 [|1; 0; 1|]
 [|1; 1; 0|]
 [|1; 1; 1|]

Однако, когда я использую PSeq для распараллеливания сгенерированной последовательности, все значения, которые должны быть использованы, изменяются на [| 2; 0; 0|], которое является последним значением массива currentPositions в цикле while выше.

Если я использую

yield (currentPositions|>Array.copy) 

вместо

yield currentPositions

, все работает нормально вкак последовательные, так и параллельные версии.

Почему это происходит;Есть ли самый эффективный способ получить результат;Заранее спасибо;

1 Ответ

3 голосов
/ 02 октября 2011

Проблема в том, что вы создаете массив single , который вы изменяете между итерациями.

Вы можете вывести параллелизм из уравнения, построив список результатов вместо того, чтобы распечатывать их один за другим - если вы сначала строите список и , то распечатываете их все, вы увидите тот же результат; список будет содержать одну и ту же ссылку 8 раз, всегда один и тот же экземпляр массива.

В основном, чтобы избежать побочных эффектов, каждый результат должен быть независимым от другого, поэтому каждый раз следует создавать отдельный массив.

...