c#平行.为了意想不到的结果
本文关键字:结果 意想不到 平行 | 更新日期: 2023-09-27 18:07:33
我是c#的新手,在翻译我的旧DSP, VB6代码时,我想利用这种语言提供的可能性。具体来说,我正在尝试使用并行处理来加快时间昂贵的计算。
这是我目前正在测试的(简化的)代码。
"1°并行代码OK"部分工作正常,没有问题;
"2°并行代码错误结果"部分,对我来说,应该相当于"顺序代码OK"部分,比顺序版本快得多,但没有返回预期的结果。
为什么?我哪里错了?
double[] Omega = new double[NFreq + 1];
double[,] SinOmT = new double[NFreq + 1, NVAL];
double[,] CosOmT = new double[NFreq + 1, NVAL];
double OmT;
// 1° Parallel code OK:
Parallel.For(0, NFreq + 1, JF =>
{
Omega[JF] = PI2 * Freq[JF] / Fs;
});
// Sequential code OK:
for (int JF = 1; JF <= NFreq; JF++)
{
for (int JD = 0; JD < NVAL; JD++)
{
OmT = Omega[JF] * (double)(JD);
SinOmT[JF, JD] = Math.Sin(OmT);
CosOmT[JF, JD] = Math.Cos(OmT);
}
}
// 2° Parallel code WRONG results:
for (int JF = 1; JF <= NFreq; JF++)
{
Parallel.For(0, NVAL, JD =>
{
OmT = Omega[JF] * (double)(JD);
SinOmT[JF, JD] = Math.Sin(OmT);
CosOmT[JF, JD] = Math.Cos(OmT);
});
}
谢谢大家的关注。
弗兰克在循环之外声明变量OmT
是错误的,因为这样并行迭代就会争夺它并不可预测地覆盖它的值。
在c#中,你应该总是在最紧凑的范围内声明变量。这适用于所有场景,而不仅仅是并行代码。
var OmT = Omega[JF] * (double)(JD);
SinOmT[JF, JD] = Math.Sin(OmT);
CosOmT[JF, JD] = Math.Cos(OmT);
变量JF被lambda表达式捕获;这意味着它将始终具有相同的值。