2016-03-01 2 views
0

Ну у меня есть эта функция для сравнения красный, синий, зеленый и альфа пикселей в сравнении изображений для цикла сравнения двух изображенийсравнение Байт использует так много процессорного

Код:

var o = 255 - c1.A; 
var t = tolerance < o ? o : tolerance; 
var b = AreSimiliar(ref c1.B, ref c2.B, ref t); 
var g = AreSimiliar(ref c1.G, ref c2.G, ref t); 
var r = AreSimiliar(ref c1.R, ref c2.R, ref t); 
if (b && g && r) continue; 

[MethodImpl(MethodImplOptions.AggressiveInlining)] 
private static bool AreSimiliar(ref byte v1, ref byte v2, ref double tolerance) 
{ 
    var z = v1 - v2; 
    var t = z > 0 ? z : -z; 
    return t <= tolerance; 
} 

Проблема заключается в том он использует так много CPU, хотя внешний код не используется, и тестирование сузило его до того кода, который вызывает нагрузку.

+1

I сомневаюсь, что будет полезно оптимизировать только этот код. Вероятно, любая реалистичная оптимизация потребует тщательного изучения окружающего кода. –

+4

не используйте ref на байте, если вы не хотите их изменить ... ваша передача указателя 32-битного или 64-битного вместо 8 бит ... на самом деле удалить все ref из этого метода – Fredou

+0

Кроме того, 'tolerance' может быть int так как дельта будет также. –

ответ

2

попробовать это вместо

var o = 255 - c1.A; 
var t = tolerance < o ? o : tolerance; 
if (AreSimiliar(c1.B, c2.B, t) && 
    AreSimiliar(c1.G, c2.G, t) && 
    AreSimiliar(c1.R, c2.R, t)) continue; 

[MethodImpl(MethodImplOptions.AggressiveInlining)] 
private static bool AreSimiliar(byte v1, byte v2, double tolerance) 
{ 
    var z = v1 - v2; 
    var t = z > 0 ? z : -z; 
    return t <= tolerance; 
} 

это может быть даже лучше

 var o = 255 - c1.A; 
     var t = tolerance < o ? o : tolerance; 
     if (Abs(c1.B - c2.B) <= t) & //or && 
      Abs(c1.G - c2.G) <= t) & //or && 
      Abs(c1.R - c2.R) <= t)) continue; 

    [MethodImpl(MethodImplOptions.AggressiveInlining)] 
    private static int Abs(int d) 
    { 
     int y = (d >> 31); 

     return (d^y) - y; 
    } 
+2

Использование '&&' для короткого замыкания фактического расчета, а не сравнение результатов должно ускорить его! – stuartd

+0

@stuartd точно – Fredou

+0

Было бы также полезно профилировать обратное, используя '&', чтобы избежать ветвления, которое '&&' добавляет. Код в вопросе был хуже обоих миров (дублирование усилий и ветвления), но работа, выполненная в «AreSimilar», не является достаточно большой, чтобы сделать короткое замыкание очевидного выбора без проблем и недостаточно для того, чтобы избежать ветви без проблем очевидный выбор, поэтому стоило бы профилировать как реалистичные данные. –

0

сделать код филиала бесплатно

использование родной SIMD (AVX, SSE) код https://en.wikipedia.org/wiki/SIMD

+1

Непонятно, что поддерживает SIMD .NET; какие шаги необходимы DEV для его включения; и какие типы поддерживают его. http://www.drdobbs.com/windows/64-bit-simd-code-from-c/240168851 и http://stackoverflow.com/questions/31906215/how-to-enable-simd-in-a- новая сетчатая рамка-4-6. Довольно интересно – MickyD

Смежные вопросы