Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2014.05.18;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.003 c
3-1297792099
AnacRon
2011-02-15 20:48
2014.05.18
Запись данных сразу в несколько таблиц


2-1375356989
14
2013-08-01 15:36
2014.05.18
Событие OnChange у DateTimePicker


15-1384508189
ПЛОВ
2013-11-15 13:36
2014.05.18
Как бы оптимизировать обмен данными?


15-1381825860
[ВладОшин]
2013-10-15 12:31
2014.05.18
Порассуждаем? Кредитная карта пришла по почте


15-1384356169
L8
2013-11-13 19:22
2014.05.18
Быстро закрасить кусок памяти





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский