在C#4.0 Parallel.For循环中找不到使用特定于线程的变量的bug

时间:2012-11-27 21:25:25

标签: c# c#-4.0 parallel-processing task-parallel-library

我试图使用基类(SlotBase)对并行编程建模老虎机行为,该基类将被代表每台机器的类覆盖。

在基类中,我有一个方法(尝试)调用后代类的方法(在基类中标记为抽象),该方法播放样本并通过使用输出参数返回结果,然后使用互斥锁,更新基类的求和变量。

相关代码示例如下: 来自SlotBase.cs:

#region Member Variables
protected long m_CoinIn;
protected long[] m_CoinOut;
protected string[] m_FeatureList;
protected long[] m_HitCount;
// .. and many more, but redacted for length
#endregion


protected abstract void PlaySample(long sampleSize, out long coinIn, out long[] coinOut, out long[] hitCount);

protected override void DoSimulation() {
    // No need to intialize these, as the calling routine will, and only it knows how big the arrays need to be, and so forth.
    object mutex = new object();

    if (ParallelMode) {
        int periodCount = (int)(BatchSize / PeriodSize);
        Parallel.For(0, periodCount, delegate(int i) {
            long coinIn;
            long[] coinOut;
            long[] hitCount;

            PlaySample(PeriodSize, out coinIn, out coinOut, out hitCount);
            lock (mutex) {
                Console.WriteLine("Coin in this batch: {0}", coinIn);
                m_CoinIn += coinIn;

                for (int j = 0; j < m_FeatureList.Length; ++j) {
                    m_CoinOut[j] += coinOut[j];
                    m_HitCount[j] += hitCount[j];
                }
            }
        });
    }
}

..来自典型的子类实现:

protected override void PlaySample(long sampleSize, out long coinIn, out long[] coinOut, out long[] hitCount) {
    switch (WagerIndex) {
        case (int)WagerType.Main: {
            RNG localRNG = SpawnRNG();
            coinIn = 0;
            coinOut = new long[m_FeatureList.Length];
            hitCount = new long[m_FeatureList.Length];


            for (long iter = 0; iter < sampleSize; ++iter) {
                coinIn += m_LinesPlayed;
                double[] output = GetSpinResults(ref localRNG, (int)SpinMode.MainSpin);

                for (int i = 0; i < m_FeatureList.Length; ++i) {
                    coinOut[i] += (long)output[i];
                    if (output[i] > 0) ++hitCount[i];
                }
            }                   
            break;
        }
        default: {
            throw new Exception(string.Format("Wager Type index {0} not supported", WagerIndex));
        }
    }
}

..这实际上对于 SampleSize PeriodSize 的小值非常有效,但随着值的增加,很快就会挂起(或虚拟挂起)。

我已经尝试评论变量更新并且认真地继续悬挂,这表明问题实际上与我实现 Parallel.For 循环的方式有关。

我没有任何问题从头开始拆除它并重建以使其正常工作。我唯一非常重要的设计目标是我有相同的范例(一个基类,多个子类用于实现不同的插槽)。

我哪里错了?

0 个答案:

没有答案