我正在尝试为 sobel 编写更快的代码,但我无法理解将其用于多个 for 循环?
我应该使用与循环数量一样多的并行吗?
这有效吗?
有人可以用代码解释一下吗:这是代码:
for (int y = 0; y < Image.Height; y++)
{
for (int x = 0; x < Image.Width * 3; x += 3)
{
r_x = g_x = b_x = 0; //reset the gradients in x-direcion values
r_y = g_y = b_y = 0; //reset the gradients in y-direction values
location = x + y * ImageData.Stride; //to get the location of any pixel >> location = x + y * Stride
for (int yy = -(int)Math.Floor(weights_y.GetLength(0) / 2.0d), yyy = 0; yy <= (int)Math.Floor(weights_y.GetLength(0) / 2.0d); yy++, yyy++)
{
if (y + yy >= 0 && y + yy < Image.Height) //to prevent crossing the bounds of the array
{
for (int xx = -(int)Math.Floor(weights_x.GetLength(1) / 2.0d) * 3, xxx = 0; xx <= (int)Math.Floor(weights_x.GetLength(1) / 2.0d) * 3; xx += 3, xxx++)
{
if (x + xx >= 0 && x + xx <= Image.Width * 3 - 3) //to prevent crossing the bounds of the array
{
location2 = x + xx + (yy + y) * ImageData.Stride; //to get the location of any pixel >> location = x + y * Stride
sbyte weight_x = weights_x[yyy, xxx];
sbyte weight_y = weights_y[yyy, xxx];
//applying the same weight to all channels
b_x += buffer[location2] * weight_x;
g_x += buffer[location2 + 1] * weight_x; //G_X
r_x += buffer[location2 + 2] * weight_x;
b_y += buffer[location2] * weight_y;
g_y += buffer[location2 + 1] * weight_y;//G_Y
r_y += buffer[location2 + 2] * weight_y;
}
}
}
}
//getting the magnitude for each channel
b = (int)Math.Sqrt(Math.Pow(b_x, 2) + Math.Pow(b_y, 2));
g = (int)Math.Sqrt(Math.Pow(g_x, 2) + Math.Pow(g_y, 2));//G
r = (int)Math.Sqrt(Math.Pow(r_x, 2) + Math.Pow(r_y, 2));
if (b > 255) b = 255;
if (g > 255) g = 255;
if (r > 255) r = 255;
//getting grayscale value
grayscale = (b + g + r) / 3;
//thresholding to clean up the background
//if (grayscale < 80) grayscale = 0;
buffer2[location] = (byte)grayscale;
buffer2[location + 1] = (byte)grayscale;
buffer2[location + 2] = (byte)grayscale;
//thresholding to clean up the background
//if (b < 100) b = 0;
//if (g < 100) g = 0;
//if (r < 100) r = 0;
//buffer2[location] = (byte)b;
//buffer2[location + 1] = (byte)g;
//buffer2[location + 2] = (byte)r;
}
}
最佳答案
最重要的问题是:工作是否可以轻松并行,以及您使用的对象模型支持并发。纯粹与数学相关且结果不是累积的事物往往可以并行化,但我无法评论对象模型的线程安全性。无法保证(默认值通常为“否”)。
至于哪里:
嵌套并行性没有什么意义;并行性会产生开销,而放大这些开销会适得其反。处理并行性的最有效方法是考虑“ block ”——即相对少量的重要操作(但希望至少与可用的 CPU 核心一样多),而不是大量的琐碎操作。因此,最有效的并行位置通常是:最外层循环。在这种情况下,这似乎映射到图像中的行,这似乎是分区图像处理的合理方法。您可以将其分区为 N 个(对于 N 个 CPU 核心),但说实话:我怀疑行可以正常工作,并且让事情变得简单。
但是!请注意,您需要避免共享状态:r_x
、g_x
和 b_x
以及 _y
部分(以及任何其他共享的局部变量)需要在并行部分内声明,以确保它们是独立的。其他需要注意的事项:灰度
、位置
、位置2
、r
、g
,b
,yyy
,xxx
。很高兴看到这些东西当前在哪里声明,但我怀疑它们都需要移动,以便它们在并行部分内声明。检查声明的所有本地变量以及访问的所有字段。
看起来 buffer
和 buffer2
只是输入/输出数组,在这种情况下:它们在这种情况下应该工作正常。
关于c# - 如何使用 "parallel for"而不是使用几个 "for"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69642977/