0

我目前正在尝试改进我正在从事的 C# 项目。具体来说,我的目标是并行化一些操作以减少处理时间。我从小片段开始只是为了掌握它。以下代码(非并行)正常工作(如预期的那样)

for (int i = 0; i < M; i++)
{
     double d;
     try
     {
          d = Double.Parse(lData[i]);
     }
     catch (Exception)
     {
         throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
     }
     sg[lCount % N][i] = d;
}

通过使用以下(并行)代码,我希望获得完全相同的结果,但事实并非如此。

Parallel.For(0, M, i =>
{
    double d;
    try
    {
        d = Double.Parse(lData[i]);
    }
    catch (Exception)
    {
        throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
    }
    sg[lCount % N][i] = d;
});

这些片段来自程序的一部分,从文件中读取数据,一次一行。每行都是逗号分隔的双精度数字序列,我使用 String.Split() 将其放入向量 lData[] 中。每 M 行,数据序列从一个新的数据帧开始(因此% M在我分配值时在元素索引中)。

我的理解(显然是错误的)是通过将(串行)for循环中的代码放在Parallel.For我并行执行的第三个参数中。这不应该改变结果。问题在于线程都在访问 lCount 和 M 吗?我应该制作线程本地副本吗?

谢谢。

(因为我是新手,所以不允许创建Parallel.For标签)

编辑:我进行了更多测试。基本上,我在代码中比以前更早地查看了输出。看来我的代码的并行版本并没有sg[][]完全填充数组。相反,某些值保留为默认值(在我的情况下为 0)。

编辑2(回答一些评论): lData[]string[]通过使用获得的string.Split()。我要拆分的原始字符串是从我的数据文件中读取的。我编写了生成它们的代码,因此它们通常格式正确(我仍然try-catch出于习惯使用该构造)。就在 for 循环(并行或串行)之前,我检查以验证是否lData[]具有正确数量的值(M)。如果没有,我会抛出一个异常,阻止程序到达有问题的 for 循环。 sg[][]是一个 N x M 类型的数组double(片段中有错字,现在已更正;在我的原始代码中,此错误不存在)。在我从文件中读取 N 行之后,数组sg[][]包含一个完整的数据集。在 for 循环(并行或串行)之后有一部分 come 如下所示: lCount++; //计算我已经读过的行 if((lCount % N) == 0) { //do things with sg[][] //reset sg[][] } 所以,我故意覆盖所有行sg[][]. for 循环的全部目的是更新sg[][].

4

2 回答 2

3

在周末做了一些逐行调试之后,我设法找到了问题所在。

基本上,我不知道,由创建的线程parallel.for没有继承 CultureInfo(这是线程的正常行为,我不知道)。当时发生的事情是字符串 like3.256被解析为3256.0. 这导致了我在输出中发现的问题。(注意:我的计算机上的默认语言环境设置为使用逗号作为小数分隔符,但我在 program.cs 中为我的所有代码设置了句号。我错误地认为这将被新线程继承)

正确的并行代码片段如下所示:

CultureInfo newCulture = (CultureInfo)CultureInfo.CurrentCulture.Clone();
newCulture.NumberFormat.NumberDecimalSeparator = ".";
Parallel.For(0, M, i =>
{
    Thread.CurrentThread.CurrentCulture = newCulture;
    double d;
    try
    {
        d = Double.Parse(lData[i]);
    }
    catch (Exception)
    {
        throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
    }
    GlobalVar.sgData[lCount % N][i] = d;
});

感谢所有提出意见和意见的人。改善我的编程的好信息。

我更新了问题标签以反映问题的真正所在。

于 2013-08-12T17:05:55.450 回答
2

据我所知,代码中没有任何东西本质上是错误的。我的猜测是您在包含片段的函数中存在竞争条件或关闭问题,可能在变量上N

如果您将此片段嵌套在另一个 Parallel.For() 调用中,您可能会错过N在 lambda 表达式中关闭的事实,并且可能正在更新。因此,当您关闭更新“N”时,您希望它在 lambda 内保持不变。要解决此问题,请尝试以下操作:

// Create a local copy of N and M, so that if we update 
// it elsewhere it doesn't affect the closure
var n = N;
var m = M;
Parallel.For(0, m, i =>
{
    double d;
    try
    {
        d = Double.Parse(lData[i]);
    }
    catch (Exception)
    {
        throw new Exception("Wrong formatting on data number " + (i + 1) + " on line " + (lCount + 1));
    }
    sg[lCount % n][i] = d;
});
于 2013-08-11T02:33:06.467 回答