Автор Тема: Blur на разных ЯП.  (Прочитано 48142 раз)

trurl

  • Full Member
  • ***
  • Сообщений: 133
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #105 : Май 07, 2013, 02:19:56 pm »
Прирост в 2.5 раза!
Ух ты! У меня прирост от непроверки далеко не такой.

Еще один страшный вариант.
MODULE TestBlur3;
  IMPORT Kernel,SYSTEM, Out:=StdLog;

  CONST
    W = 640;
    H = 480;
    N = 13;
    Frames = 1000;

  TYPE
Pixel = ARRAY 4 OF BYTE;
    Plane = ARRAY H*W OF Pixel;
   
  VAR 
    a, b : Plane;

  PROCEDURE Blur*;
  VAR
    f, n : INTEGER;
    x, y, z : INTEGER;
q1, q2, q3, q4: SET;
    time1, time2 : LONGINT;     
    fps:REAL;
  CONST
    MaskRB = {0..7,16..23};
  BEGIN
    time1 := Kernel.Time();

    FOR f:=1 TO Frames DO
      FOR n:=1 TO N DO
       z:= W+1;
       FOR y:= 1 TO H-2 DO
         FOR x:= 1 TO W-2 DO
           q1:=SYSTEM.VAL(SET, a[z + 1]);
           q2:=SYSTEM.VAL(SET, a[z - 1]);
           q3:=SYSTEM.VAL(SET, a[z + W]);
           q4:=SYSTEM.VAL(SET, a[z - W]);
           SYSTEM.PUT(SYSTEM.ADR(b[z]),
                BITS( (ORD(q1*MaskRB) + ORD(q2*MaskRB) + ORD(q3*MaskRB) + ORD(q4*MaskRB)) DIV 4)
              + BITS( (ORD(q1-MaskRB) + ORD(q2-MaskRB) + ORD(q3-MaskRB) + ORD(q4-MaskRB)) DIV 4));
           INC(z);
          END;
          INC(z,2);
        END;

        z:= W+1;
        FOR y:=1 TO H-2 DO
          FOR x:=1 TO W-2 DO
           z:= y*W+x;
           q1:=SYSTEM.VAL(SET, b[z + 1]);
           q2:=SYSTEM.VAL(SET, b[z - 1]);
           q3:=SYSTEM.VAL(SET, b[z + W]);
           q4:=SYSTEM.VAL(SET, b[z - W]);
           SYSTEM.PUT(SYSTEM.ADR(a[z]),
                BITS( (ORD(q1*MaskRB) + ORD(q2*MaskRB) + ORD(q3*MaskRB) + ORD(q4*MaskRB)) DIV 4)
              + BITS( (ORD(q1-MaskRB) + ORD(q2-MaskRB) + ORD(q3-MaskRB) + ORD(q4-MaskRB)) DIV 4));
           INC(z);
          END;
          INC(z,2);
        END;
      END
    END;

    time2 := Kernel.Time();
    fps:=Frames*1000/(time2 - time1);
    Out.String("t="); Out.Real((time2 - time1)/1000);
    Out.String(" fps="); Out.Real(fps);
    Out.Ln;
  END Blur;

END TestBlur3.

DevCompiler.CompileThis TestBlur3!!
TestBlur3.Blur

DddIzer

  • Гость
Re: Blur на разных ЯП.
« Ответ #106 : Май 07, 2013, 02:48:29 pm »
тык какой результат то ?

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #107 : Май 07, 2013, 05:40:32 pm »
Пока писал версию для двумерного массива, понял, что неправильно соптимизировал версию для одномерного.
Второй заход:
для N=13
одномерный массив - больше 1.5 минуты
двумерный - больше 3 минут

MODULE WorkBlur;
IMPORT Log, Kernel, SYSTEM;

CONST W = 640; H = 480; (* размер кадра в пикселях *)
ln = 1;
clr = 3;
w = (W - 1) * clr; h = H -1; (* размер области кадра на обработке *)
w2 = W * clr;
shift = -2;
F = 1000; (* кол-во кадров *)

PROCEDURE Do*(N : INTEGER);
VAR a1, a2 : POINTER TO ARRAY OF BYTE;
len : INTEGER;
f, n, x, y : INTEGER;
m : INTEGER;
time : LONGINT;
BEGIN
time := Kernel.Time();
len := W * H * clr;
NEW( a1, len );
NEW( a2, len );
f := 0;
WHILE f < F DO

n := 0;
WHILE n < N DO
m := w + 6;

y := 1;
WHILE y < h DO
x := 3;
WHILE x < w DO
a2[m] := SHORT(SHORT(SYSTEM.LSH(a1[m - w2] + a1[m - clr] + a1[m + clr] + a1[m + w2], shift)));
m := m + 1;
x := x + 1
END;
m := m + 6;
y := y + 1
END;

(*<-->*)

m := w + 6;

y := 1;
WHILE y < h DO
x := 3;
WHILE x < w DO
a1[m] := SHORT(SHORT(SYSTEM.LSH(a2[m - w2] + a2[m - clr] + a2[m + clr] + a2[m + w2], shift)));
m := m + 1;
x := x + 1
END;
m := m + 6;
y := y + 1
END;

n := n + 1
END;
f := f + 1
END;
Log.Int(SHORT(Kernel.Time() - time))
END Do;

PROCEDURE Do2*(N : INTEGER);
VAR  a1, a2 : POINTER TO ARRAY OF ARRAY OF BYTE;
len : INTEGER;
f, n, x, y : INTEGER;
time : LONGINT;
BEGIN
time := Kernel.Time();
NEW( a1, H, W * 3 );
NEW( a2, H, W * 3 );
f := 0;

WHILE f < F DO

n := 0;
WHILE n < N DO
y := 1;
WHILE y < h DO
x := 3;
WHILE x < w DO
a2[y, x] := SHORT(SHORT(SYSTEM.LSH(a1[y - ln, x] + a1[y, x - clr] + a1[y, x + clr] + a1[y + ln, x], shift)));
x := x + 1
END;
y := y + 1
END;

y := 1;
WHILE y < h DO
x := 3;
WHILE x < w DO
a1[y, x] := SHORT(SHORT(SYSTEM.LSH(a2[y - ln, x] + a2[y, x - clr] + a2[y, x + clr] + a2[y + ln, x], shift)));
x := x + 1
END;
y := y + 1
END;

n := n + 1
END;
f := f + 1
END;
Log.Int(SHORT(Kernel.Time() - time))
END Do2;

END WorkBlur.

Прогнал.

== With array bound checks ===
BB/CB (Valery Solovey 1D):
   time: 131 seconds
   fps : 7.6
BB/CB (Valery Solovey 2D):
   time: 261 seconds
   fps : 3.8
== Without array bound checks ===
BB/CB (Valery Solovey 1D):
   time: 103 seconds
   fps : 9.7 fps
BB/CB (Valery Solovey 2D):
   time: 158 seconds
   fps : 6.3
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #108 : Май 07, 2013, 05:50:55 pm »
Прирост в 2.5 раза!
Ух ты! У меня прирост от непроверки далеко не такой.
А процессор какой? У меня мобильный i5. Подозреваю что у разных процессоров алгоритм предсказания немного разный. А ветвления (любые) сильно мешают алгоритму предсказания и увеличивают промахи кеша.

Еще один страшный вариант.
MODULE TestBlur3;
  IMPORT Kernel,SYSTEM, Out:=StdLog;

  CONST
    W = 640;
    H = 480;
    N = 13;
    Frames = 1000;

  TYPE
Pixel = ARRAY 4 OF BYTE;
    Plane = ARRAY H*W OF Pixel;
   
  VAR 
    a, b : Plane;

  PROCEDURE Blur*;
  VAR
    f, n : INTEGER;
    x, y, z : INTEGER;
q1, q2, q3, q4: SET;
    time1, time2 : LONGINT;     
    fps:REAL;
  CONST
    MaskRB = {0..7,16..23};
  BEGIN
    time1 := Kernel.Time();

    FOR f:=1 TO Frames DO
      FOR n:=1 TO N DO
       z:= W+1;
       FOR y:= 1 TO H-2 DO
         FOR x:= 1 TO W-2 DO
           q1:=SYSTEM.VAL(SET, a[z + 1]);
           q2:=SYSTEM.VAL(SET, a[z - 1]);
           q3:=SYSTEM.VAL(SET, a[z + W]);
           q4:=SYSTEM.VAL(SET, a[z - W]);
           SYSTEM.PUT(SYSTEM.ADR(b[z]),
                BITS( (ORD(q1*MaskRB) + ORD(q2*MaskRB) + ORD(q3*MaskRB) + ORD(q4*MaskRB)) DIV 4)
              + BITS( (ORD(q1-MaskRB) + ORD(q2-MaskRB) + ORD(q3-MaskRB) + ORD(q4-MaskRB)) DIV 4));
           INC(z);
          END;
          INC(z,2);
        END;

        z:= W+1;
        FOR y:=1 TO H-2 DO
          FOR x:=1 TO W-2 DO
           z:= y*W+x;
           q1:=SYSTEM.VAL(SET, b[z + 1]);
           q2:=SYSTEM.VAL(SET, b[z - 1]);
           q3:=SYSTEM.VAL(SET, b[z + W]);
           q4:=SYSTEM.VAL(SET, b[z - W]);
           SYSTEM.PUT(SYSTEM.ADR(a[z]),
                BITS( (ORD(q1*MaskRB) + ORD(q2*MaskRB) + ORD(q3*MaskRB) + ORD(q4*MaskRB)) DIV 4)
              + BITS( (ORD(q1-MaskRB) + ORD(q2-MaskRB) + ORD(q3-MaskRB) + ORD(q4-MaskRB)) DIV 4));
           INC(z);
          END;
          INC(z,2);
        END;
      END
    END;

    time2 := Kernel.Time();
    fps:=Frames*1000/(time2 - time1);
    Out.String("t="); Out.Real((time2 - time1)/1000);
    Out.String(" fps="); Out.Real(fps);
    Out.Ln;
  END Blur;

END TestBlur3.

DevCompiler.CompileThis TestBlur3!!
TestBlur3.Blur

Результаты прогонов страшного варианта:
BB/CB (trurl/SYSTEM with array bound checks)
   time: 81 seconds
   fps : 12.2
BB/CB (trurl/SYSTEM without array bound checks)
   time: 77 seconds
   fps : 13.0
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #109 : Май 07, 2013, 08:10:11 pm »
Кстати, о корректности: в исходных данных картинки мы имеем набор unsigned char'ов, то есть беззнаковых целых в диапазоне от 0 до 255. Насколько я понимаю, в КП у нас таки тип BYTE знаковый, соответственно нужно как-то конвертировать наверное...

Вообще, как корректно биндинг строится к функции вида:
bool __stdcall PXCUPipeline_QueryRGB(PXCUPipeline_Instance instance, unsigned char *data);

?
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #110 : Май 07, 2013, 08:45:38 pm »
Кстати, о корректности: в исходных данных картинки мы имеем набор unsigned char'ов, то есть беззнаковых целых в диапазоне от 0 до 255. Насколько я понимаю, в КП у нас таки тип BYTE знаковый, соответственно нужно как-то конвертировать наверное...

Вообще, как корректно биндинг строится к функции вида:
bool __stdcall PXCUPipeline_QueryRGB(PXCUPipeline_Instance instance, unsigned char *data);

?
Если посмотреть на жабу, то там unsigned char отображают тупо в int. То есть был массив байт, стал массив 4байтных целых. Причем так, что один пиксель == одно целое 4 байтное число, RGBA.

Ну и соответственно, чтобы как-то с этим жить, там есть замечательные функции вида:
Цитировать
public final float green(int rgb)

Extracts the green value from a color, scaled to match current colorMode(). This value is always returned as a float so be careful not to assign it to an int value.

The green() function is easy to use and undestand, but is slower than another technique. To achieve the same results when working in colorMode(RGB, 255), but with greater speed, use the >> (right shift) operator with a bit mask. For example, the following two lines of code are equivalent:
float r1 = green(myColor);
float r2 =
 myColor >> 8 & 0xFF;

Parameters:
rgb - any value of the color datatype

Ну и конечно функция для создания данных для одного пикселя:
public final int color(int v1,
        int v2,
        int v3,
        int a)
Y = λf.(λx.f (x x)) (λx.f (x x))

ilovb

  • Hero Member
  • *****
  • Сообщений: 2538
  • just another nazi test
    • Просмотр профиля
    • Oberon systems
Re: Blur на разных ЯП.
« Ответ #111 : Май 08, 2013, 06:28:09 am »
Мне кажется что не нужно конвертить. Должно так работать.

trurl

  • Full Member
  • ***
  • Сообщений: 133
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #112 : Май 08, 2013, 06:34:24 am »
Кстати, о корректности: в исходных данных картинки мы имеем набор unsigned char'ов, то есть беззнаковых целых в диапазоне от 0 до 255. Насколько я понимаю, в КП у нас таки тип BYTE знаковый, соответственно нужно как-то конвертировать наверное...
Да, надо. Либо MOD 256 добавлять, либо вместо BYTE использовать SHORTCHAR.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #113 : Май 11, 2013, 07:31:29 pm »
Oberon-07/11

Теперь этот вариант можно скомпилить и запустить прямо в браузере - см. шапку форума ;) Компилятор сырой, но подрихтованный вариант akron1 он компилит (я закомментировал импорты)
MODULE Blur;

  (*IMPORT dt := DateTime, In, Out, RTL;*)

  CONST
    W = 640; W1 = 640 - 3;
    H = 480; H1 = 480 - 3;
    N = 13;
    Frames = 1;

  TYPE
    Plane = ARRAY W*3, H OF CHAR;

  VAR
    a, b:  Plane;
    time: LONGREAL;

  PROCEDURE Blur2DArray*;
  VAR
    f, n : INTEGER;
    x, y : INTEGER;
    color : INTEGER;
  BEGIN
    FOR f:=1 TO Frames DO
      FOR n:=1 TO N DO
        FOR y:=1 TO H-2 DO
          FOR x:=1 TO W-2 DO
            FOR color:=0 TO 2 DO
              b[x*3+color,y] := CHR((ORD(a[x*3+color,y+1])+ORD(a[x*3+color,y-1])+ORD(a[(x-1)*3,y])+ORD(a[(x+1)*3,y])) DIV 4);
            END
          END
        END;
        FOR y:=1 TO H-2 DO
          FOR x:=1 TO W-2 DO
            FOR color:=0 TO 2 DO
              a[x*3+color,y] := CHR((ORD(b[x*3+color,y+1])+ORD(b[x*3+color,y-1])+ORD(b[(x-1)*3,y])+ORD(b[(x+1)*3,y])) DIV 4);
            END
          END
        END
      END
    END;
  END Blur2DArray;

BEGIN
  (*In.Open;
  Out.Open;
  time := dt.Now();*)
  Blur2DArray;
  (*Out.FixReal(LONG(FLT(Frames))/((dt.Now() - time) * 86400.D0), 20, 5);
  In.Ln;*)
END Blur.

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #114 : Май 11, 2013, 07:36:03 pm »
Oberon-07/11

Теперь этот вариант можно скомпилить и запустить прямо в браузере - см. шапку форума ;) Компилятор сырой, но подрихтованный вариант akron1 он компилит (я закомментировал импорты)
MODULE Blur;

  (*IMPORT dt := DateTime, In, Out, RTL;*)

  CONST
    W = 640; W1 = 640 - 3;
    H = 480; H1 = 480 - 3;
    N = 13;
    Frames = 1;

  TYPE
    Plane = ARRAY W*3, H OF CHAR;

  VAR
    a, b:  Plane;
    time: LONGREAL;

  PROCEDURE Blur2DArray*;
  VAR
    f, n : INTEGER;
    x, y : INTEGER;
    color : INTEGER;
  BEGIN
    FOR f:=1 TO Frames DO
      FOR n:=1 TO N DO
        FOR y:=1 TO H-2 DO
          FOR x:=1 TO W-2 DO
            FOR color:=0 TO 2 DO
              b[x*3+color,y] := CHR((ORD(a[x*3+color,y+1])+ORD(a[x*3+color,y-1])+ORD(a[(x-1)*3,y])+ORD(a[(x+1)*3,y])) DIV 4);
            END
          END
        END;
        FOR y:=1 TO H-2 DO
          FOR x:=1 TO W-2 DO
            FOR color:=0 TO 2 DO
              a[x*3+color,y] := CHR((ORD(b[x*3+color,y+1])+ORD(b[x*3+color,y-1])+ORD(b[(x-1)*3,y])+ORD(b[(x+1)*3,y])) DIV 4);
            END
          END
        END
      END
    END;
  END Blur2DArray;

BEGIN
  (*In.Open;
  Out.Open;
  time := dt.Now();*)
  Blur2DArray;
  (*Out.FixReal(LONG(FLT(Frames))/((dt.Now() - time) * 86400.D0), 20, 5);
  In.Ln;*)
END Blur.

Нюанс - в этом исходнике обрабатывается ОДИН кадр (Frames = 1). Так что не удивляйтесь быстрому завершению работы алгоритма. :-)
Y = λf.(λx.f (x x)) (λx.f (x x))

akron1

  • Jr. Member
  • **
  • Сообщений: 76
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #115 : Май 11, 2013, 08:00:28 pm »
Обнаружил ошибку в сравнении целых

MODULE test;
IMPORT JS;
VAR x: INTEGER;
BEGIN
    x := 10;
    IF x >= 0 THEN
      JS.alert("TRUE")
    ELSE
      JS.alert("FALSE")
    END
END test.

строка
IF x >= 0 THEN

транслируется так
if (RTL$.setInclR(x, 0))

и естественно не работает как надо, похоже, что компилятор применяет операцию ">=" перегруженную для множеств.
Операции ">" и "<" для целых не работают вообще, пишет: TypeError: Cannot call method 'replace' of undefined.
Кстати операции ">=" и "<=" для множеств тоже работают неправильно:
MODULE test;
IMPORT JS;
VAR s1, s2: SET;
BEGIN
    s1 := {0..5};
    s2 := {0..8};
    IF s1 <= s2 THEN
      JS.alert("TRUE")
    ELSE
      JS.alert("FALSE")
    END
END test.
Программа пишет "FALSE" (должно быть "TRUE")

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #116 : Май 11, 2013, 08:25:52 pm »
Обнаружил ошибку в сравнении целых

Спасибо! Буду фиксить :)

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #117 : Май 14, 2013, 05:20:06 pm »
Начал проверку на корректность алгоритмов. Пока проверил код генерируемый компилятором vlad'a - он выдает корректный результат (то есть это Oberon-07/11). И проверил js-реализацию.

Планирую как минимум проверить следующие реализации: C#, C++, CB/BB (несколько), Oberon-07 (две под винду), возможно Lua-jit.

Oberon-2, F#, Ada, Delphi, Java, Fortran скорее всего окажутся пока за бортом - у меня просто на них времени и сил не хватит.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #118 : Май 25, 2013, 01:36:17 am »
GPCP for .NET. Наивная реализация алгоритма. Ключи компиляции: /nodebug /nocheck (/nocheck убирает проверку целочисленного переполнение - это дает выигрыш в два раза, суммарно эти две опции дают выигрыш примерно в 10 раз).

Время работы: 171 секунда.
Для сравнения, примерно то же самое в ББ работает порядка 560 секунд.

Наивная реализация:
MODULE Blur;
    IMPORT CPmain;
   
    CONST
        width = 640;
        height = 480;
        N = 13;
        frames = 1000;
       
        red = 0;
        green = 1;
        blue = 2;
       
    TYPE
        Frame = ARRAY width*height*(blue+1) OF SHORTCHAR;
           
    PROCEDURE Index(x,y,color : INTEGER) : INTEGER;
    BEGIN
        RETURN ((x+y*width)*3+color)
    END Index;
   
    PROCEDURE Blur(IN in : Frame; OUT out : Frame);
    VAR
        x,y,c : INTEGER;
    BEGIN
        FOR y:=1 TO height-2 DO
            FOR x:=1 TO width-2 DO
                FOR c:=red TO blue DO
                    out[Index(x,y,c)] := SHORT(CHR( ( ORD(in[Index(x,y-1,c)]) + ORD(in[Index(x,y+1,c)]) +
                                                            ORD(in[Index(x-1,y,c)]) + ORD(in[Index(x+1,y,c)]) ) DIV 4  ));
                END;
            END;
        END;
    END Blur;
   
    PROCEDURE Do*;
    VAR
        time : LONGINT;
        f, n : INTEGER;
        a1, a2 : POINTER TO Frame;
    BEGIN
        NEW(a1);
        NEW(a2);
       
        FOR f:=1 TO frames DO
            FOR n:=1 TO N DO               
                Blur(a1,a2);
                Blur(a2,a1)
            END
        END;
    END Do;
BEGIN
    Do;
END Blur.
Y = λf.(λx.f (x x)) (λx.f (x x))

valexey_u

  • Hero Member
  • *****
  • Сообщений: 3013
    • Просмотр профиля
Re: Blur на разных ЯП.
« Ответ #119 : Май 25, 2013, 03:00:12 am »
В компиляторе vlad'а не реализованы встроенные процедуры-функции вроде ROR, ASR и так далее. Зарепортил: https://github.com/vladfolts/oberonjs/issues/4
Y = λf.(λx.f (x x)) (λx.f (x x))