平行班不提供任何提速 - c#

我正在尝试创建一种方法,该方法将过滤掉低于给定灰度阈值的所有像素(例如,下面的全部为黑色,上面的全部为白色)。该方法有效,但并没有我想象的那么快。

我决定使用Parallel类,但是无论我设置什么MaxDegreeOfParallelism我都不会获得任何速度上的好处。我也对位图执行其他一些操作,无论MaxDegreeOfParallelism是什么,操作的总时间始终约为170 ms。调试时,执行此过滤本身所需的时间约为160毫秒,因此我认为总体差异会很大。

我正在使用i7处理器,4个物理核心,8个逻辑核心。

代码:

Color black = System.Drawing.Color.FromArgb(0, 0, 0);
Color white = System.Drawing.Color.FromArgb(255, 255, 255);

int lowerBound = (int)((float)lowerBoundPercent * 255.0 / 100.0);
int upperBound = (int)((float)upperBoundPercent * 255.0 / 100.0);

int[][] border = new int[8][];
for (int i=0;i<8;i++)
{
    border[i] = new int[] { i*height/8, (i+1)*height/8-1};
}

Parallel.For(0, 8, new ParallelOptions { MaxDegreeOfParallelism = 8 }, i =>
    {
        for (int k = 0; k < width; k++)
        {
            for (int j = border[i][0]; j <= border[i][1]; j++)
            {
                Color pixelColor;
                int grayscaleValue;
                pixelColor = color[k][j];
                grayscaleValue = (pixelColor.R + pixelColor.G + pixelColor.B) / 3;
                if (grayscaleValue >= lowerBound && grayscaleValue <= upperBound)
                    color[k][j] = white;
                else
                    color[k][j] = black;
            }
        }
    });

color[][]System.Drawing.Color的锯齿状数组。

问题:这正常吗?如果没有,我该怎么做才能改变它?

编辑:

像素提取:

Color[][] color;
color = new Color[bitmap.Width][];
for (int i = 0; i < bitmap.Width; i++)
{
    color[i] = new Color[bitmap.Height];
    for (int j = 0; j < bitmap.Height; j++)
    {
        color[i][j] = bitmap.GetOriginalPixel(i, j);
    }
}

位图是我自己的类位图的一个实例:

public class Bitmap
{
    System.Drawing.Bitmap processed;
    //...
    public Color GetOriginalPixel(int x, int y) { return processed.GetPixel(x, y); }
    //...
}

参考方案

要回答有关为什么并行方法没有更快的主要问题,Parralel.For仅从一个线程开始,然后添加更多thead,因为它检测到更多线程可能有助于加快工作速度,请注意parallel选项MaxDegreeOfParallelism不仅是DegreeOfParallelism。很简单,循环的迭代次数不足,无法启动足够多的线程才能生效,因此您需要减少每次迭代的工作量。

尝试通过宽度的循环而不是高度的8个块来给并行操作做更多的工作。

Color black = System.Drawing.Color.FromArgb(0, 0, 0);
Color white = System.Drawing.Color.FromArgb(255, 255, 255);

int lowerBound = (int)((float)lowerBoundPercent * 255.0 / 100.0) * 3;
int upperBound = (int)((float)upperBoundPercent * 255.0 / 100.0) * 3;

Parallel.For(0, width, k =>
    {
        for (int j = 0; j < height; j++)
        {
                Color pixelColor;
                int grayscaleValue;
                pixelColor = color[k][j];
                grayscaleValue = (pixelColor.R + pixelColor.G + pixelColor.B);
                if (grayscaleValue >= lowerBound && grayscaleValue <= upperBound)
                    color[k][j] = white;
                else
                    color[k][j] = black;
        }
    });

我不会同时进行宽度和高度的选择,然后您可能会遇到一个相反的问题,即不给每个迭代足够的工作。

我强烈建议您下载并阅读Patterns for Parallel Programming,在讨论您应该为Parallel.For做多少工作时,它进入了这个确切的示例。从C#版本的第26页底部开始,查看“非常小的循环体”和“太细粒度,太粗粒度”的反模式,以查看运行中的确切问题。

我还将研究使用LockBits来读入和读出像素数据,而不是像我们在评论中讨论的那样使用GetPixel和SetPixel。

45码

在PHP中使用long int - php

我正在尝试此方法,但无法存储较大的价值$var = rand(100000000000000,999999999999999); echo $var; // prints a 9 digit value(largest possible) 如何获得期望值? 参考方案 PHP整数通常为32位。其他软件包提供了更高精度的整数:http://php.net/man…

Parallel.Foreach在幕后做什么? - c#

所以我只是在这里无法理解这个概念。我有一个使用Parallel类和Foreach方法的方法。但是我不明白的是,它会创建新线程以便更快地运行该函数吗?让我们以此为例。我做一个普通的foreach循环。private static void DoSimpleWork() { foreach (var item in collection) { //DoWork(…

为什么我的按位运算不能在Java中与`int`一起使用? - java

我刚得到以下编译器错误:./package/path/FrameScreenPosition.java:80: incompatible types found : int required: boolean if (frame.getExtendedState() & Frame.MAXIMIZED_BOTH) { ^ “扩展状态”是各种不同状态的…

在AtomicInteger.addAndGet(int)中使用无限循环 - java

在Java包中,java.util.concurrent.atomic AtomicInteger类具有方法addAndGet(int)这是public final int addAndGet(int delta) { for (;;) { int current = get(); int next = current + delta; if (compar…

通过List <int>在函数参数中传递超过10个lac记录? - c#

我遇到的情况是数据库中有10多个lac记录。当用户使用某些选定的记录在MVC中点击我的操作方法时,我想通过获取所有记录并将它们与用户传递的记录进行比较来检查这些记录是否存在于数据库中。然后我想将所有这些记录传递给另一个函数。在函数参数中传递这么多记录是否安全?这是一个演示:- //Action Method [HttpGet] Public ActionRe…