[英]How to speed up this calculation
鑒於兩個ARGB顏色表示為整數,8位/通道(alpha,紅色,綠色,藍色),我需要計算一個值,表示它們之間的一種距離(也是整數)。
因此距離的公式為: Delta=|R1-R2|+|G1-G2|+|B1-B2|
其中Rx,Gx和Bx是顏色1和2的通道值.Alpha通道始終被忽略。
我需要加快這個計算速度,因為在慢速機器上進行了很多次。 在給定兩個整數的情況下,在單個線程上計算這個的'geekies'方法是什么。
到目前為止,我最好的是,但我想這可以進一步改進:
//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 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();
}
輸出是:6878
所以7億次1億次看起來相當不錯。
我們絕對可以加快速度。 我改變你的功能看起來像這樣:
public static int ComputeColorDelta(int color1, int color2) {
return 1;
}
隨着這一變化,輸出為: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();
}
一個想法是使用您已有的相同代碼,但順序不同:應用掩碼,取差異,然后移動。
可能有幫助的另一個修改是內聯這個函數:也就是說,不是為每對顏色調用它,而是直接計算差異,在任何循環中執行此代碼。 我認為它是在一個緊湊的循環內,因為否則它的成本可以忽略不計。
最后,由於您可能正在獲取圖像像素數據,因此通過使用unsafe
路徑可以節省很多:使您的位圖像這個EditableBitmap ,然后獲取字節*並從中讀取圖像數據。
您可以這樣做以減少AND操作:
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;
}
不多但是......
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.