c# - 如何使用 "parallel for"而不是使用几个 "for"?

标签 c# image-processing parallel-processing parallel.for

我正在尝试为 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_xg_xb_x 以及 _y 部分(以及任何其他共享的局部变量)需要在并行部分内声明,以确保它们是独立的。其他需要注意的事项:灰度位置位置2rgbyyyxxx。很高兴看到这些东西当前在哪里声明,但我怀疑它们都需要移动,以便它们在并行部分内声明。检查声明的所有本地变量以及访问的所有字段。

看起来 bufferbuffer2 只是输入/输出数组,在这种情况下:它们在这种情况下应该工作正常。

关于c# - 如何使用 "parallel for"而不是使用几个 "for"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69642977/

相关文章:

c# - 在运行时更改类应用程序中的连接字符串?

javascript - JS/jQuery 图像编辑器

opencv - opencv hog.cpp中的 Gamma 校正

java - 在 Java 流 : combine filters or combine circumstances? 的性能方面有什么更好的

c# - 如何使用 Roslyn 内部类?

c# - 在大型列表中查找具有相同属性的对象 - 性能缓慢

c# - 使用正则表达式解析数据

c++ - Opencv 数据类型定义

windows - *Windows* 中的并行 Cucumber/Watir 场景

performance - 如何并行化小型纯函数?