【发布时间】:2012-01-19 15:34:17
【问题描述】:
我正在用 C# 创建一个图像处理应用程序,并尝试通过并行执行大部分处理来利用我的多核系统。具体来说,我有一个 Parallel.For 循环遍历每个像素并应用高斯滤波器。正如预期的那样,仅执行计算,我就看到了显着的加速,但是在尝试保存计算结果时出现了问题。代码如下所示:
Parallel.For(// various loop parameters
{
// processing and number crunching
// significant speed up here
.
.
.
bitmap.SetPixel(x, y, value);
});
这会产生运行时错误,因为多个线程最终会尝试同时写入位图对象。我将对象锁定如下:
lock(bitmap)
bitmap.SetPixel(x, y, value);
但这最终会比串行版本慢。检查后发现,每次循环迭代对 SetPixel 的调用占用了大约 90% 的运行时间,这意味着单独的线程将大部分时间用于等待获取位图对象上的锁,并且增加了开销拥有多个线程会减慢它的速度。
所以我想知道的是,有没有办法让多个线程同时写入同一个对象?我很小心每个线程都在处理图像的不同部分,因此不会引入竞争条件。有没有办法覆盖抛出的错误并说:“我知道我正在做的事情是不安全的,但我还是想这样做?” Concurrency::combinable 类之类的东西似乎可以解决问题,但这仅在 C++ 中。
【问题讨论】:
-
将位图分割成几个不同的对象,并行处理它们,完成后重新创建完整的东西是否可行?
-
好问题。实际上我已经尝试过了——我手动创建了自己的线程,给它们每个单独的位图并在最后手动组合它们,但是增加的开销也最终使它比串行版本慢。
标签: c# concurrency parallel-processing