代码之家  ›  专栏  ›  技术社区  ›  Steve W

对于完成C的循环,代码似乎在并行之前继续前进#

  •  0
  • Steve W  · 技术社区  · 3 年前

    我很难使用 Parallel.For 循环。我可以告诉他们他们真的加快了我长时间运行的代码,但我得到了空对象错误,就好像代码在完成并行循环之前移动了一样。下面是我的代码,已注释掉 平行的对于 我尝试过的陈述。

    public bool Calculate()
    {
        // make list of all possible flops 22100
        List<Flop> flops = new List<Flop>();
        CardSet deck = new CardSet();
        for (int i = 0; i < deck.Size() - 2; i++)
        {
            SbCard card1 = deck.GetCard(i);
            for (int j = i + 1; j < deck.Size() - 1; j++)
            {
                SbCard card2 = deck.GetCard(j);
                for (int k = j + 1; k < deck.Size(); k++)
                {
                    SbCard card3 = deck.GetCard(k);
                    flops.Add(new Flop(card1, card2, card3));
                }
            }
        }
    
        int progress = 0;
        var watch = System.Diagnostics.Stopwatch.StartNew();
    
        // Loop over each flop
        //Parallel.For(0, flops.Count, i =>
        for (int i = 0; i < flops.Count; i++)
        {
            Dictionary<FlopEquityHoldemHandPair, FlopEquityHoldemHandPair> flopPairs =
            new Dictionary<FlopEquityHoldemHandPair, FlopEquityHoldemHandPair>();
            Flop flop = flops[i];
            String filePath = Directory.GetCurrentDirectory() + "\\flops\\" +
            flop.GetSorted() + ".txt";
    
            if (!File.Exists(filePath))
            {
                // make list of all available starting hands
                List<HoldemHand> hands = new List<HoldemHand>();
                deck = new CardSet();
                deck.RemoveAll(flop);
                for (int j = 0; j < deck.Size() - 1; j++)
                {
                    SbCard card1 = deck.GetCard(j);
                    for (int k = j + 1; k < deck.Size(); k++)
                    {
                        SbCard card2 = deck.GetCard(k);
                        hands.Add(new HoldemHand(card1, card2));
                    }
                }
    
                // loop over all hand vs hand combos
                //Parallel.For(0, hands.Count - 1, j =>
                for (int j = 0; j < hands.Count - 1; j++)
                {
                    HoldemHand hand1 = hands[j];
                    //Parallel.For(j + 1, hands.Count, k =>
                    for (int k = j + 1; k < hands.Count; k++)
                    {
                        HoldemHand hand2 = hands[k];
                        if (!hand1.Contains(hand2))
                        {
                            FlopEquityHoldemHandPair holdemHandPair = new
                              FlopEquityHoldemHandPair(hand1, hand2);
                            if (!flopPairs.ContainsKey(holdemHandPair))
                            {
                                // next line triggers a loop of 1980 iterations
                                flopPairs.Add(holdemHandPair, new
                                FlopEquityHoldemHandPair(new
                                EquityHoldemHand(hand1), new
                                EquityHoldemHand(hand2), flop));
                            }
                        }
                    }//);
                }//);
    
    
                // WRITE FILE FOR CURRENT FLOP
                StringBuilder sb = new StringBuilder();
                foreach (FlopEquityHoldemHandPair pair in flopPairs.Values)
                {
                    // Null value appears in flopPairs.Values and the list of values is around 200 short of the 600k values it should have
                    sb.AppendLine(pair.ToString());
                }
                File.WriteAllText(filePath, sb.ToString());
    
                // reports calculation progress 1% at a time
                int num = ((int)(i * 100 / 22100));
                if (num > progress)
                {
                    progress = num;
                    Console.WriteLine("Progress: " + progress + "%");
                }
            }
        }//);
    
        watch.Stop();
        var elapsedMs = watch.ElapsedMilliseconds;
    
        Console.WriteLine("Finished in " + elapsedMs / 60000 + "mins");
        return true;
    }
    

    当我到达 foreach 循环,flopPairs中的一些项。值为null,字典没有达到应有的大小-就好像有些计算在代码继续之前没有完成一样。很抱歉,如果没有更多的代码,这段代码就无法运行,但有很多东西可以提供。我可以尝试提供一个最小化的简化示例,如果问题对某人来说不是很明显,则可以运行该示例。

    0 回复  |  直到 3 年前
        1
  •  0
  •   Steve W    3 年前

    正如John Wu在评论中所说,Dictionary不是线程安全的,这给我带来了问题。使用ConcurrentDictionary是正确的答案