Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2014.05.18;
Скачать: CL | DM;

Вниз

Быстро закрасить кусок памяти   Найти похожие ветки 

 
L8   (2013-11-13 19:22) [0]

Имеется 32-битное изображение, его нужно быстро закрасить одним цветом.
Нашел такую функцию:


procedure FillDWORD(var Dest; Count, Value: LongInt); register;
asm
 XCHG  EDX, ECX
 PUSH  EDI
 MOV   EDI, EAX
 MOV   EAX, EDX
 REP   STOSD
 POP   EDI
end;

Использование:
FillDWORD(PByteArray(PtrImage)[0], Image.Width * Image.Height, $FF0000);


Вопрос, как сеё дело ускорить и нет ли в этом ассемблере, который я естественно не знаю, какая-нибудь брешь. Которая даст о себе знать при,
например, переносе программы на 64-бит.


 
Inovet ©   (2013-11-13 19:37) [1]

> [0] L8   (13.11.13 19:22)
> Которая даст о себе знать при,
> например, переносе программы на 64-бит.

Есть, не будет работать, там другой ассемблер.


 
L8   (2013-11-13 19:41) [2]


> Inovet ©   (13.11.13 19:37) [1]
>
> > [0] L8   (13.11.13 19:22)
> > Которая даст о себе знать при,
> > например, переносе программы на 64-бит.
>
> Есть, не будет работать, там другой ассемблер.
>


Иногда пишут 4 * X, вместо SizeOf(DWORD) * X.
Не будет это работать.


 
Павиа   (2013-11-13 19:48) [3]


> Использование:FillDWORD(PByteArray(PtrImage)[0], Image.Width
> * Image.Height, $FF0000);

Тут цикл нужен.


> Имеется 32-битное изображение, его нужно быстро закрасить
> одним цветом.Нашел такую функцию:procedure FillDWORD(var
> Dest; Count, Value: LongInt); register;asm  XCHG  EDX, ECX
>  PUSH  EDI  MOV   EDI, EAX  MOV   EAX, EDX  REP   STOSD
>  POP   EDIend;

А смысл?? Обычно это не требуется. В любом случае взять готовую библиотеку.


 
Rouse_ ©   (2013-11-13 19:49) [4]


> Вопрос, как сеё дело ускорить и нет ли в этом ассемблере,
>  который я естественно не знаю, какая-нибудь брешь. Которая
> даст о себе знать при,
> например, переносе программы на 64-бит.

Ускорить можно и нужно, т.к. инструкция "REP   STOSD" достаточно медлительная. Для 64 бит работать также будет (если убрать работу со стеком), но тже медленно.

Вот как-то так:

procedure FillDWORD(var Dest; Count, Value: LongInt); register;
asm
XCHG  EDX, ECX
// PUSH  EDI
MOV   EDI, EAX
MOV   EAX, EDX
REP   STOSD
// POP   EDI
end;


ЗЫ: правда у меня дома только 32 бита и проверить не могу, но должно...


 
Rouse_ ©   (2013-11-13 19:57) [5]

ЗЫ: В общем случае, стандартный FillChar реализованный в Delhi 2005 и выше (с реализацией через FPU) будет пошустрее этого кода.


 
брат Птибурдукова   (2013-11-13 20:00) [6]


> // PUSH  EDI
An asm statement must preserve the EDI, ESI, ESP, EBP, and EBX registers, but can freely modify the EAX, ECX, and EDX registers


> инструкция "REP   STOSD" достаточно медлительная
А что вместо? MMX? Для 8086 как раз REP STOSx рекомендовали использовать. Некоторые источники даже намекали, что при этом перепрограммируется КПДП, и данные идут через него :о)


 
Rouse_ ©   (2013-11-13 20:11) [7]


> An asm statement must preserve the EDI, ESI, ESP, EBP, and
> EBX registers,

Ну это я показал чтобы скомпилялась под 64


> А что вместо?

Ручками MOV + JNE


 
Rouse_ ©   (2013-11-13 20:12) [8]


> Ручками MOV + JNE

ЗЫ: + FPU конечно.


 
jack128_   (2013-11-13 20:43) [9]


> ЗЫ: В общем случае, стандартный FillChar реализованный в
> Delhi 2005 и выше (с реализацией через FPU) будет пошустрее
> этого кода.

жаль только FillChar не решает задачу топикстартера ;-)


 
все арамисы, а я Дартаньян   (2013-11-13 20:56) [10]


> Rouse_ ©   (13.11.13 20:11) [7]
MOV быстрее STOS? о_О


 
Dimka Maslov ©   (2013-11-13 20:56) [11]

Давным давно я проводил тесты и у меня получалось, что REP STOSx получалось медленнее, чем цикл с MOV [eax+ecx], xx и LOOP


 
Павиа   (2013-11-13 21:01) [12]


> > инструкция "REP   STOSD" достаточно медлительнаяА что
> вместо? MMX? Для 8086 как раз REP STOSx рекомендовали использовать.
>  Некоторые источники даже намекали, что при этом перепрограммируется
> КПДП, и данные идут через него :о)

Для i7 тоже STOSD вместо MOV.
Правда SIMD будет быстрее любого их этого.


+ FPU конечно.

А что мелочиться тогда уж GPU. Или ПЛИС.


 
Павиа   (2013-11-13 21:04) [13]


> MOV быстрее STOS? о_О

Быстрее только надо знать на каком процессоре.


 
Rouse_ ©   (2013-11-13 21:17) [14]


> jack128_   (13.11.13 20:43) [9]
> жаль только FillChar не решает задачу топикстартера ;-)

Лолшто?


> все арамисы, а я Дартаньян   (13.11.13 20:56) [10]
> MOV быстрее STOS? о_О

По тактам монопенисюально, кабы не цикл через REP


> Dimka Maslov ©   (13.11.13 20:56) [11]
> Давным давно я проводил тесты и у меня получалось, что REP
> STOSx получалось медленнее, чем цикл с MOV [eax+ecx], xx
> и LOOP

LOOP - тоже одна из причин задержек (минус такт) Jxx в данном случае выгодней.


> А что мелочиться тогда уж GPU. Или ПЛИС.

А я не мелочусь, я говорю как есть. Да ну на GPU для такой задачи также будет просадка (зачем гонять буфера для такой тривиальной задачи)?


 
Rouse_ ©   (2013-11-13 21:22) [15]

ЗЫ: на данный момент самый оптимальный вариант (используемый кстати в составе Delphi выглядит в реализации от John O"Harrow).

procedure _FillChar(var Dest; Count: NativeInt; Value: _AnsiChr);
asm                                  // Size = 153 Bytes
       CMP   EDX, 32
       MOV   CH, CL                 // Copy Value into both Bytes of CX
       JL    @@Small
       MOV   [EAX  ], CX            // Fill First 8 Bytes
       MOV   [EAX+2], CX
       MOV   [EAX+4], CX
       MOV   [EAX+6], CX
       SUB   EDX, 16
       FLD   QWORD PTR [EAX]
       FST   QWORD PTR [EAX+EDX]    // Fill Last 16 Bytes
       FST   QWORD PTR [EAX+EDX+8]
       MOV   ECX, EAX
       AND   ECX, 7                 // 8-Byte Align Writes
       SUB   ECX, 8
       SUB   EAX, ECX
       ADD   EDX, ECX
       ADD   EAX, EDX
       NEG   EDX
@@Loop:
       FST   QWORD PTR [EAX+EDX]    // Fill 16 Bytes per Loop
       FST   QWORD PTR [EAX+EDX+8]
       ADD   EDX, 16
       JL    @@Loop
       FFREE ST(0)
       FINCSTP
       RET
       NOP
       NOP
       NOP
@@Small:
       TEST  EDX, EDX
       JLE   @@Done
       MOV   [EAX+EDX-1], CL        // Fill Last Byte
       AND   EDX, -2                // No. of Words to Fill
       NEG   EDX
{$IFDEF PIC}
       PUSH  EAX
       PUSH  EBX
       PUSH  ECX
       CALL  GetGOT
       ADD   EAX, offset @@SmallFill + 60
       LEA   EDX, [EAX + EDX * 2]
       POP   ECX
       POP   EBX
       POP   EAX
{$ELSE !PIC}
       LEA   EDX, [@@SmallFill + 60 + EDX * 2]
{$ENDIF !PIC}
       JMP   EDX
{$IFNDEF PIC}
       NOP                          // Align Jump Destinations
       NOP
{$ENDIF !PIC}
@@SmallFill:
       MOV   [EAX+28], CX
       MOV   [EAX+26], CX
       MOV   [EAX+24], CX
       MOV   [EAX+22], CX
       MOV   [EAX+20], CX
       MOV   [EAX+18], CX
       MOV   [EAX+16], CX
       MOV   [EAX+14], CX
       MOV   [EAX+12], CX
       MOV   [EAX+10], CX
       MOV   [EAX+ 8], CX
       MOV   [EAX+ 6], CX
       MOV   [EAX+ 4], CX
       MOV   [EAX+ 2], CX
       MOV   [EAX   ], CX
       RET                          // DO NOT REMOVE - This is for Alignment
@@Done:
end;


Достаточно красиво и оптимально без использования как LOOP так и REP STOSx


 
Sapersky   (2013-11-13 21:22) [16]

FillChar заполняет байтами, а нужно DWord (цвет). Хотя это почти то же самое, и при желании можно допилить какой-нибудь вариант FillChar из FastCode:
http://www.fastcode.dk/fastcodeproject/fastcodeproject/25.htm


 
Rouse_ ©   (2013-11-13 21:23) [17]

Особливо красиво выглядит концовка ввиде:
LEA   EDX, [@@SmallFill + 60 + EDX * 2]
JMP   EDX


 
Rouse_ ©   (2013-11-13 21:24) [18]


> Sapersky   (13.11.13 21:22) [16]
> FillChar заполняет байтами, а нужно DWord (цвет).

Она заполняет по 16 байт + концовка...


 
antonn ©   (2013-11-13 21:24) [19]


> Иногда пишут 4 * X, вместо SizeOf(DWORD) * X.
> Не будет это работать.

dword же всегда 4 байта?


 
Sapersky   (2013-11-13 21:28) [20]

Роуз, алё, проснись. У цвета значения RGBA могут быть разные, а FillChar заполняет всё одним байтом. Хотя, если нужно очищать чёрным или белым, то сойдёт и FillChar.


 
Rouse_ ©   (2013-11-13 21:31) [21]


> Sapersky   (13.11.13 21:28) [20]
> Роуз, алё, проснись. У цвета значения RGBA могут быть разные,
>  а FillChar заполняет всё одним байтом. Хотя, если нужно
> очищать чёрным или белым, то сойдёт и FillChar.

Ыц...
Воть это я лажанулся :)
Пардон - был не прав :)))


 
все арамисы, а я Дартаньян   (2013-11-13 21:40) [22]


> или белым
…то 255 в старшем байте может дать забавные эффекты, не?


 
Inovet ©   (2013-11-13 22:04) [23]

> [14] Rouse_ ©   (13.11.13 21:17)
> LOOP - тоже одна из причин задержек (минус такт) Jxx в данном
> случае выгодней.

REP ещё понимаю, а LOOP зачем они выпиливают. Так и не собрался с этим разобраться.


 
Rouse_ ©   (2013-11-13 22:13) [24]


> а LOOP зачем они выпиливают. Так и не собрался с этим разобраться.

Три такта против двух.


 
Inovet ©   (2013-11-13 22:16) [25]

> [24] Rouse_ ©   (13.11.13 22:13)
> Три такта против двух.

Так я про интеловцев. Что их вынудило сделать 3 такта. Казалось бы, должно быть наоборот.


 
Sapersky   (2013-11-13 22:45) [26]


> …то 255 в старшем байте может дать забавные эффекты, не?

Это по-моему фишка исключительно VCL - воспринимать TColor с битом в старшем разряде как системный цвет, т.е. индекс в системной палитре. И я сомневаюсь, что это относится к содержимому битмапов (хотя бы из соображений производительности - для каждого пикселя дёргать GetSysColor накладно).
А при самостоятельной обработке можно использовать 4-й байт как угодно. Если это альфа-канал, то всё логично - будет полная непрозрачность.



Страницы: 1 вся ветка

Текущий архив: 2014.05.18;
Скачать: CL | DM;

Наверх




Память: 0.54 MB
Время: 0.007 c
15-1384174248
Joker87
2013-11-11 16:50
2014.05.18
Распределенная разработка проекта


15-1383152239
Rouse_
2013-10-30 20:57
2014.05.18
Требуется небольшая вычитка статьи.


2-1375017722
SkAndriy
2013-07-28 17:22
2014.05.18
Delphi XE4 функция StrPCopy не рекомендована


11-1250509132
Демьян
2009-08-17 15:38
2014.05.18
Закрыть все модальные формы


15-1384751257
[ВладОшин]
2013-11-18 09:07
2014.05.18
reverse engineering oracle forms