Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/315.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何加快计算速度_C#_Performance - Fatal编程技术网

C# 如何加快计算速度

C# 如何加快计算速度,c#,performance,C#,Performance,给定两个用整数表示的ARGB颜色,8位/通道(alpha、红色、绿色、蓝色),我需要计算一个表示它们之间某种距离(也是整数)的值 所以距离的公式是:Delta=|R1-R2 |+| G1-G2 |+| B1-B2 |,其中Rx、Gx和Bx是颜色1和2的通道值。Alpha通道始终被忽略 我需要加速这个计算,因为在一台速度较慢的机器上要做很多次。对于给定两个整数的单个线程,“极客”是如何计算的 到目前为止,我的最好成绩是,但我想这还可以进一步提高: //Used for color conv

给定两个用整数表示的ARGB颜色,8位/通道(alpha、红色、绿色、蓝色),我需要计算一个表示它们之间某种距离(也是整数)的值

所以距离的公式是:
Delta=|R1-R2 |+| G1-G2 |+| B1-B2 |
,其中Rx、Gx和Bx是颜色1和2的通道值。Alpha通道始终被忽略

我需要加速这个计算,因为在一台速度较慢的机器上要做很多次。对于给定两个整数的单个线程,“极客”是如何计算的

到目前为止,我的最好成绩是,但我想这还可以进一步提高:

    //Used for color conversion from/to int
    private const int ChannelMask = 0xFF;
    private const int GreenShift = 8;
    private const int RedShift = 16;

    public int ComputeColorDelta(int color1, int color2)
    {
        int rDelta = Math.Abs(((color1 >> RedShift) & ChannelMask) - ((color2 >> RedShift) & ChannelMask));
        int gDelta = Math.Abs(((color1 >> GreenShift) & ChannelMask) - ((color2 >> GreenShift) & ChannelMask));
        int bDelta = Math.Abs((color1 & ChannelMask) - (color2 & ChannelMask));

        return rDelta + gDelta + bDelta;
    }

您可以这样做以减少和操作:

public int ComputeColorDelta(int color1, int color2)
{
    int rDelta = Math.Abs((((color1  >> RedShift) - (color2  >> RedShift))) & ChannelMask)));
    // same for other color channels

    return rDelta + gDelta + bDelta;
}

不是很多,但有些东西…

一个想法是使用与您已有的代码相同的代码,但顺序不同:应用掩码,获取差异,然后移位

另一个可能有用的修改是内联这个函数:也就是说,不需要为每一对颜色调用它,只需在执行此代码的任何循环中直接计算差异。我假设它处于一个紧密的循环中,因为否则它的成本可以忽略不计

最后,由于您可能正在获取图像像素数据,您可以通过执行
不安全的
路线节省大量资源:这样制作位图,然后抓取字节*并从中读取图像数据。

详细答案:

多少是“很多”

我想我有一台速度很快的机器,但我写了这个小脚本:

 public static void Main() {
            var s = Stopwatch.StartNew();
            Random r = new Random();
            for (int i = 0; i < 100000000; i++) {
                int compute = ComputeColorDelta(r.Next(255), r.Next(255));
            }
            Console.WriteLine(s.ElapsedMilliseconds);
            Console.ReadLine();
        }
根据这一变化,输出为:5546。因此,通过返回一个常量,我们在1亿次迭代中获得了1秒的性能增益。;)


简短回答:此功能不是您的瓶颈。:)

我试图让运行时为我计算

首先,我用显式字段偏移量定义struct

[StructLayout(LayoutKind.Explicit)]
public struct Color
{
    [FieldOffset(0)] public int Raw;
    [FieldOffset(0)] public byte Blue;
    [FieldOffset(8)] public byte Green;
    [FieldOffset(16)] public byte Red;
    [FieldOffset(24)] public byte Alpha;
}
计算功能将是:

public int ComputeColorDeltaOptimized(Color color1, Color color2)
{
    int rDelta = Math.Abs(color1.Red - color2.Red);
    int gDelta = Math.Abs(color1.Green - color2.Green);
    int bDelta = Math.Abs(color1.Blue - color2.Blue);

    return rDelta + gDelta + bDelta;
}
以及用法

public void FactMethodName2()
{
    var s = Stopwatch.StartNew();
    var color1 = new Color(); // This is a structs, so I can define they out of loop and gain some performance
    var color2 = new Color(); 
    for (int i = 0; i < 100000000; i++)
    {
        color1.Raw = i;
        color2.Raw = 100000000 - i;
        int compute = ComputeColorDeltaOptimized(color1, color2);
    }
    Console.WriteLine(s.ElapsedMilliseconds); //5393 vs 7472 of original 
    Console.ReadLine();
}
public void FactMethodName2()
{
var s=Stopwatch.StartNew();
var color1=new Color();//这是一个结构,因此我可以在循环外定义它们并获得一些性能
var color2=新颜色();
对于(int i=0;i<100000000;i++)
{
颜色1.Raw=i;
颜色2.原始值=100000000-i;
int compute=ComputeColorDeltaOptimized(color1,color2);
}
Console.WriteLine(s.elapsedmillyses);//5393对7472的原始版本
Console.ReadLine();
}

前两个问题:您确定这是您的瓶颈吗?你是通过分析确定的吗?我不认为这有什么错。这似乎不太可能是瓶颈。您是否分析过以确认这是瓶颈?您是否进行了性能测试以确定当前性能是否不足?在开始之前,您是否能够轻松地将这两个映像转换为字节数组而不是整数数组?这将使计算更简单,因为您只需在不进行任何移位的情况下找到字节值之间的差异。哦,如果有一种简单的方法从.Net访问SIMD就好了:)我不相信这是正确的:通道将相互干扰。考虑“0x0FF00 -0x000”FF:您的公式为绿色通道差异提供“0xFE”。你必须先将遮罩应用到每种颜色上。不,你的公式先取差值,然后移动。区别在于
0x00FE01
,移位
0x00FE
,掩蔽
0xFE
。谢谢:)记录在案,如果我发布自己的答案,我不会投反对票,所以不是我:)我想随机投票会占用大部分时间,如果您只是将
i
传递到
ComputeColorDelta
中,然后进行比较,那么运行时会怎么样?@aquinas会更改您的代码,首先将所有随机数生成到一个列表中,而使用新的StopWatch()默认构造函数,分别调用.Start()和.Stop()?我认为你的第一个衡量标准是衡量r.Next()的成本也是两倍。我只是想说明一点,我并不是说这是有史以来最好的基准:)这是一个很好的观点。但我分别得到1237和40。如果可能的话,绝对值得优化该代码。将黑色改为蓝色,但无论如何+1显示FieldOffset,我没有意识到这一点
public void FactMethodName2()
{
    var s = Stopwatch.StartNew();
    var color1 = new Color(); // This is a structs, so I can define they out of loop and gain some performance
    var color2 = new Color(); 
    for (int i = 0; i < 100000000; i++)
    {
        color1.Raw = i;
        color2.Raw = 100000000 - i;
        int compute = ComputeColorDeltaOptimized(color1, color2);
    }
    Console.WriteLine(s.ElapsedMilliseconds); //5393 vs 7472 of original 
    Console.ReadLine();
}