【发布时间】:2013-08-12 01:12:07
【问题描述】:
我目前正在尝试改进我正在从事的 C# 项目。具体来说,我的目标是并行化一些操作以减少处理时间。 我从小的 sn-ps 开始只是为了掌握它。 以下代码(非并行)正常工作(如预期)
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;
});
这些sn-ps来自的程序部分从文件中读取数据,一次一行。每行都是逗号分隔的双精度数字序列,我使用 String.Split() 将其放入向量 lData[] 中。每 M 行,数据序列从一个新的数据帧开始(因此当我分配值时元素索引中的 % M)。
我的理解(显然是错误的)是通过将(串行)for循环中的代码放在Parallel.For的第三个参数中,我可以并行化它的执行。这不应该改变结果。问题在于线程都在访问 lCount 和 M 吗?我应该制作线程本地副本吗?
谢谢。
(因为我是新手,所以不能创建Parallel.For 标签)
编辑:
我又进行了一些测试。基本上,我在代码中比以前更早地查看了输出。我的代码的并行版本似乎没有完全填充sg[][] 数组。相反,一些值保留为默认值(在我的例子中为 0)。
编辑 2(回答一些 cmets):
lData[]是使用string.Split()得到的string[]。我要拆分的原始字符串是从我的数据文件中读取的。我编写了生成它们的代码,因此它们通常格式正确(出于习惯,我仍然使用try-catch 构造)。就在 for 循环(并行或串行)之前,我检查以验证 lData[] 具有正确数量的值(M)。如果没有,我会抛出一个异常,阻止程序到达有问题的 for 循环。
sg[][] 是 double 类型的 N x M 数组(sn-ps 中有错字,现已更正;在我的原始代码中,此错误不存在)。从文件中读取 N 行后,数组sg[][] 包含整个数据集。在 for 循环(并行或串行)之后有一部分 come 如下所示:
l计数++; //计算我已经读过的行数
if((lCount % N) == 0)
{
//用sg[][]做事
//重置sg[][]
}
所以,我故意覆盖sg[][] 的所有行。 for 循环的全部目的是更新sg[][] 中的值。
【问题讨论】:
-
旁白:您可以通过使用
Double.TryParse而不是异常处理来提高性能。 -
谢谢@James,我不知道。
-
对于缺失值,您收到异常了吗?此外,如果您的处理取决于顺序,Parallel.For 不会按特定顺序执行。
-
@James:那不是真的。假设提供了有效输入,Try/catch 和 Double.TryParse 应该以相同的速度运行。当没有抛出异常时,try/catch 对性能没有影响。 msdn.microsoft.com/en-us/library/… 从他的例子来看,假设值有效且异常很少见。 stackoverflow.com/a/586539/455493 但除此之外,我同意。
Double.TryParse是一种更清洁的方式。不一定更快。 -
你是对的。这取决于异常无效数据的程度。
标签: c# task-parallel-library locale cultureinfo