我试图使用基类(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 循环的方式有关。
我没有任何问题从头开始拆除它并重建以使其正常工作。我唯一非常重要的设计目标是我有相同的范例(一个基类,多个子类用于实现不同的插槽)。
我哪里错了?