并行 C#
Parallel For c#
我正在尝试提高计算图像平均值的方法的性能。
为此,我使用了两个 For 语句来迭代所有图像,因此我尝试使用一个 Parallel For 来改进它,但结果并不相同。
我做错了吗?或者是什么造成了差异?
public static double MeanDN(this GrayImage image)
{
double mean = 0;
int totalPixels = image.Width * image.Height;
for (int i = 0; i < image.Height; i++)
for (int j = 0; j < image.Width; j++)
mean += (double)image[i, j] / totalPixels;
double parallelMean = 0;
Parallel.For(0, image.Height, i =>
{
for (int j = 0; j < image.Width; j++)
parallelMean += (double)image[i, j] / totalPixels;
});
return mean;
}
输出:
mean = 404.12
parallelMean = 148.8658
您正在访问资源(变量 parallelMean
),但没有从多个线程进行同步。有些更改会相互覆盖,有些读取会读取错误或旧数据。这就是您看到错误结果的原因。
最简单的解决方案是在对该变量的写访问周围放置一个 lock
语句,但这会迫使它返回顺序进行。
如果您需要对结果进行计算,使用 PLinq 可能会更容易,它会为您完成大部分同步工作:
var mean = Enumerable.Range(0, image.Height)
.AsParallel()
.Select(i => Enumerable.Range(0, image.Width)
.AsParallel()
.Sum(j => (double)image[i, j] / totalPixels))
.Sum();
你的问题是你让多个任务修改同一个变量parallelMean
。所以你有一个竞争条件。
我还认为第二个结果不仅是错误的,而且还不稳定:意思是再次尝试执行代码,第二个结果会改变
我认为这段代码可以解决您的问题
double[] parallelMean = new double[image.Height];
Parallel.For(0, image.Height, i =>
{
for (int j = 0; j < image.Width; j++)
parallelMean[i] += (double)image[i, j] / totalPixels;
});
return parallelMean.Sum();
我正在尝试提高计算图像平均值的方法的性能。
为此,我使用了两个 For 语句来迭代所有图像,因此我尝试使用一个 Parallel For 来改进它,但结果并不相同。
我做错了吗?或者是什么造成了差异?
public static double MeanDN(this GrayImage image)
{
double mean = 0;
int totalPixels = image.Width * image.Height;
for (int i = 0; i < image.Height; i++)
for (int j = 0; j < image.Width; j++)
mean += (double)image[i, j] / totalPixels;
double parallelMean = 0;
Parallel.For(0, image.Height, i =>
{
for (int j = 0; j < image.Width; j++)
parallelMean += (double)image[i, j] / totalPixels;
});
return mean;
}
输出:
mean = 404.12
parallelMean = 148.8658
您正在访问资源(变量 parallelMean
),但没有从多个线程进行同步。有些更改会相互覆盖,有些读取会读取错误或旧数据。这就是您看到错误结果的原因。
最简单的解决方案是在对该变量的写访问周围放置一个 lock
语句,但这会迫使它返回顺序进行。
如果您需要对结果进行计算,使用 PLinq 可能会更容易,它会为您完成大部分同步工作:
var mean = Enumerable.Range(0, image.Height)
.AsParallel()
.Select(i => Enumerable.Range(0, image.Width)
.AsParallel()
.Sum(j => (double)image[i, j] / totalPixels))
.Sum();
你的问题是你让多个任务修改同一个变量parallelMean
。所以你有一个竞争条件。
我还认为第二个结果不仅是错误的,而且还不稳定:意思是再次尝试执行代码,第二个结果会改变
我认为这段代码可以解决您的问题
double[] parallelMean = new double[image.Height];
Parallel.For(0, image.Height, i =>
{
for (int j = 0; j < image.Width; j++)
parallelMean[i] += (double)image[i, j] / totalPixels;
});
return parallelMean.Sum();