用于共享内部变量的 C# 并行

本文关键字:并行 变量 共享 内部 用于 | 更新日期: 2023-09-27 18:33:25

嗨,我正在处理以下代码:

            Parallel.For(1, residRanges.Count, i =>
            {
                int count = 0;
                List<double> colAList = new List<double>();
                List<double> colBList = new List<double>();
                for (int x = 0; x < residErrorData.Count; x++)
                {
                    foreach (pricateConnection in residErrorData[x].connList)
                    {
                        if (residRanges[i].connection == nc.connection)
                        {
                            colAList.Add(residErrorData[x].residualError);
                            colBList.Add(nc.freq);
                            count = count + 1;
                        }
                    }
                }
                colA = new double[count];
                colB = new double[count];
                for (int j = 0; j < count; j++)
                {
                    colA[j] = colAList[j];
                    colB[j] = colBList[j];
                }
                residRangeError tempresid = residRanges[i];
                tempresid = fitResid(tempresid, colA, colB);                    
                residRanges[i] = tempresid;
                residRanges[i].n = count;                        
                }
            });

如果我不使用并行类,我的值似乎是准确的,但是当我出于某种原因使用并行类时,它会混淆 colA 和 colB 的值。它在线程之间混合它们。 我对并行处理相当陌生,但我一直在四处寻找,似乎找不到任何解决方案。 有谁知道为什么程序似乎在线程之间共享变量?

我知道代码并不理想,我一直在尝试不同的事情来找出出了什么问题。 我目前并不一定要优化它,而是要理解为什么不同循环中的变量没有保持独立。

residRanges[] 是类项的列表。 使用它的 for 循环似乎获得了正确的值,它们只是开始混淆哪些值在 Parallel.For 中运行时会去哪里。

感谢您的任何帮助! 我真的可以用它!

用于共享内部变量的 C# 并行

(重新发布作为甜蜜,甜蜜业力的答案)

您的代码看起来好像 colAcolB 是在 lambda 的作用域之外声明的,这意味着变量引用可以引用不同的数组对象,因为不同的线程同时运行(例如,线程 0 会更改colA而线程 1 在 for j < count 循环内。

colAcolB 的声明移动到 lambda 内部:

...
Double[] colA = new double[count];
Double[] colB = new double[count];
for (int j = 0; j < count; j++)
...

但是,我看到除了将它们用作fitResid函数的值持有者之外,您实际上并没有对colAcolB做任何有用的事情,您可以通过以下方式简化这一点:

  1. fitResid函数签名更改为接受IList<Double>而不是Double[]
  2. fitResid函数调用更改为分别传入colAListcolBList传入,这将通过消除不必要的复制和内存分配来加快代码速度:

    ...             
    residRanges[i] = fitResid( residRanges[i], colAList, colBList );
    residRanges[i].n = count;        
    ...