Здравствуйте, fAX, Вы писали:
fAX>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
Если нужно быстро и на x86, то, пожалуй, кроме ассемблерной вставки с REP STOSW, ничего другого не придумать. memset в реализации от M$ так и делает — заполняет массив из четырех байт младшим байтом из аргумента, натравливает на массив REP STOSW и дописывает остаток, не делящийся на 4 байта, вручную.
... << np:Queen (A Kind Of Magic '1986) Princes of the universe >> ...
Re[2]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, fAX, Вы писали:
fAX>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
unsigned int Size= 16000006;
unsigned int b= 0x80000000;
unsigned int _4= 0x31323334;
unsigned int f;
unsigned char *_mem;
_mem= new char [Size];
Здравствуйте, m.a.g., Вы писали:
MAG>>Если нужно быстро и на x86, то, пожалуй, кроме ассемблерной вставки с REP STOSW,
MAG>Очепятался, REP STOSQ, конечно.
Опять очепяточка
REP STOSD
Завидую людям, которые могут себе позволить никуда не спешить.
Re[4]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, m.a.g., Вы писали:
MAG>Здравствуйте, _Dinosaur, Вы писали:
MAG>>>Очепятался, REP STOSQ, конечно. D>>Опять очепяточка D>>REP STOSD
MAG>Да поди запомни, на какой архитектуре QWORD как называется
К сожалению, знаю только для х86 QWORD = 8 байт
Завидую людям, которые могут себе позволить никуда не спешить.
Re: Как быстро заполнить память повторяющимися 4-мя байтами
Здравствуйте, fAX, Вы писали:
fAX>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
Re: Как быстро заполнить память повторяющимися 4-мя байтами
От:
Аноним
Дата:
18.12.02 10:35
Оценка:
Здравствуйте, fAX, Вы писали:
fAX>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
относительно — это относительно
int* ptr = bufferOfInt; // например int bufferOfInt[1000];int value = 0x12345678;
int length = 1000;
for ( ;length>0; --length) *ptr++ = value;
Уважаемый Аноним, это уж как оптимизатор захочет. Я один раз видел как VC++ такую же штуку реализовал спомощью REP MOVSD!!! Т.е. сначала установил 1-е слово, а потом стал копировать ptr в (ptr+1)!!!
Работало, конечно, медленнее.
... << RSDN@Home 1.0 beta 3 >>
Кр-ть — с.т.
Re[2]: Как быстро заполнить память повторяющимися 4-мя байта
От:
Аноним
Дата:
18.12.02 17:04
Оценка:
Здравствуйте, cpp, Вы писали:
cpp>Здравствуйте, fAX, Вы писали:
fAX>>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
cpp> cpp>по-моему так: cpp>
Где-то я видел (AMD-шная статья кажется) кусок кода для быстрого копирования куска памяти (с использованием кэша, инструкций MMX и прочей фигни). При этом копирование REP MOVSD оказывается гораздо медленнее. Так что возможно есть способ гораздо быстрее REP STOSD.
Re[4]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, Дубров Иван Сергеевич, Вы писали:
ДИС>Где-то я видел (AMD-шная статья кажется) кусок кода для быстрого копирования куска памяти (с использованием кэша, инструкций MMX и прочей фигни). При этом копирование REP MOVSD оказывается гораздо медленнее. Так что возможно есть способ гораздо быстрее REP STOSD.
(bandwidth: ~1630 Mbytes/sec)
#define CACHEBLOCK 400h // QWORDs in a block (8K bytes)
mov esi, [src] // source array
mov edi, [dst] // destination array
mov ecx, [len] // total number of QWORDS (8 bytes)
// (assumes len / CACHEBLOCK = integer)
lea esi, [esi+ecx*8]
lea edi, [edi+ecx*8]
neg ecx
emms
mainloop:
mov eax, CACHEBLOCK / 16 // note: prefetch loop is unrolled 2X
prefetchloop:
mov ebx, [esi+ecx*8] // Read one address in line,
mov ebx, [esi+ecx*8+64]// and one address in the next.
add ecx, 16 // add 16 QWORDS, = 2 64-byte cache lines
dec eax
jnz prefetchloop
sub ecx, CACHEBLOCK
mov eax, CACHEBLOCK / 8
writeloop:
movq mm0, qword ptr [esi+ecx*8]
.
.
movq mm7, qword ptr [esi+ecx*8+56]
movntq qword ptr [edi+ecx*8], mm0
.
.
movntq qword ptr [edi+ecx*8+56], mm7
add ecx, 8
dec eax
jnz writeloop
or ecx, ecx
jnz mainloop
sfence
emms
Сергей.
Re[3]: Как быстро заполнить память повторяющимися 4-мя байта
От:
Аноним
Дата:
19.12.02 06:03
Оценка:
Здравствуйте, Atilla, Вы писали:
A>Уважаемый Аноним, это уж как оптимизатор захочет. Я один раз видел как VC++ такую же штуку реализовал спомощью REP MOVSD!!! Т.е. сначала установил 1-е слово, а потом стал копировать ptr в (ptr+1)!!! A>Работало, конечно, медленнее.
конечно если программа то и дело копирует память с места на место и ничем боше не занимается, то такую программу надо оптимизировать по максимуму, чтобы копировала память очень быстро и также очень быстро ничего не делала
ниже в ветке про стек сопроцессора, про ММХ... а если программу хочу запустить на Пентиуме, который 1?
с достаточно развитой логикой у программы есть узкие места, которые у вас не будет возможности оптимизировать ( файлы, сеть... )
так стоит ли улучшать скорость программы на 0.5-2% ( цифры с потолка накапали , тратя на это пару дней и ресурсы серого вещества?
копирование памяти достотачно простая и "повсеместная" задача, так что можно считать, что компилятор использует самое оптимальное решение. если за одним из них вы заметили "не порядок", нужен ли вам вообще такой компилятор, который тормозит вместо того, чтобы помогать?
Re[4]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, <Аноним>, Вы писали:
А>ниже в ветке про стек сопроцессора, про ММХ... а если программу хочу запустить на Пентиуме, который 1? А>с достаточно развитой логикой у программы есть узкие места, которые у вас не будет возможности оптимизировать ( файлы, сеть... ) А>так стоит ли улучшать скорость программы на 0.5-2% ( цифры с потолка накапали , тратя на это пару дней и ресурсы серого вещества?
Это все от ситуации зависит. Ради 2% скорее всего даже стараться не стоит.
Играет вокально-инструментальный ансамбль ... а ничего не играет. << RSDN@Home 1.0 beta 3 >>
Кр-ть — с.т.
Re[5]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, Atilla, Вы писали:
A>Здравствуйте, <Аноним>, Вы писали:
А>>ниже в ветке про стек сопроцессора, про ММХ... а если программу хочу запустить на Пентиуме, который 1? А>>с достаточно развитой логикой у программы есть узкие места, которые у вас не будет возможности оптимизировать ( файлы, сеть... ) А>>так стоит ли улучшать скорость программы на 0.5-2% ( цифры с потолка накапали , тратя на это пару дней и ресурсы серого вещества?
A>Это все от ситуации зависит. Ради 2% скорее всего даже стараться не стоит.
В том то и дело, что выигрыш чисто на копировании может быть более 400% (!!!) (насколько я помню )
Re[3]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, <Аноним>, Вы писали:
А>Здравствуйте, cpp, Вы писали:
cpp>>Здравствуйте, fAX, Вы писали:
fAX>>>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
cpp>> cpp>>по-моему так: cpp>>
Здравствуйте, cpp, Вы писали:
cpp>Здравствуйте, Дубров Иван Сергеевич, Вы писали:
ДИС>>Где-то я видел (AMD-шная статья кажется) кусок кода для быстрого копирования куска памяти (с использованием кэша, инструкций MMX и прочей фигни). При этом копирование REP MOVSD оказывается гораздо медленнее. Так что возможно есть способ гораздо быстрее REP STOSD.
cpp>(bandwidth: ~1630 Mbytes/sec) cpp>
cpp>#define CACHEBLOCK 400h // QWORDs in a block (8K bytes)
cpp> mov esi, [src] // source array
cpp> mov edi, [dst] // destination array
cpp> mov ecx, [len] // total number of QWORDS (8 bytes)
cpp> // (assumes len / CACHEBLOCK = integer)
cpp> lea esi, [esi+ecx*8]
cpp> lea edi, [edi+ecx*8]
cpp> neg ecx
cpp> emms
cpp>mainloop:
cpp> mov eax, CACHEBLOCK / 16 // note: prefetch loop is unrolled 2X
cpp>prefetchloop:
cpp> mov ebx, [esi+ecx*8] // Read one address in line,
cpp> mov ebx, [esi+ecx*8+64]// and one address in the next.
cpp> add ecx, 16 // add 16 QWORDS, = 2 64-byte cache lines
cpp> dec eax
cpp> jnz prefetchloop
cpp> sub ecx, CACHEBLOCK
cpp> mov eax, CACHEBLOCK / 8
cpp>writeloop:
cpp> movq mm0, qword ptr [esi+ecx*8]
cpp> .
cpp> .
cpp> movq mm7, qword ptr [esi+ecx*8+56]
cpp> movntq qword ptr [edi+ecx*8], mm0
cpp> .
cpp> .
cpp> movntq qword ptr [edi+ecx*8+56], mm7
cpp> add ecx, 8
cpp> dec eax
cpp> jnz writeloop
cpp> or ecx, ecx
cpp> jnz mainloop
cpp> sfence
cpp> emms
cpp>
вспоминается, как на z80 народ память забивал нулями с помощью стека. Ставится указатель стека на конец нужной области и push a, push a, push a ....
Самый быстрый метод был. Быстрее народ не придумал
для 486 самый быстрый метод использовал регистры сопроцессора.
А под Linux-ом, ядро при старте пробует десколько методов копирования памяти, выбирает самый быстрый и дальше внутри ядра только этим методом и пользуется
В общем извращаться можно долго и сильно !!!
... << RSDN@Home 1.0 beta 3 >>
Re[4]: Как быстро заполнить память повторяющимися 4-мя байта
Здравствуйте, Dmitry A. Sustretov, Вы писали:
DAS>Здравствуйте, <Аноним>, Вы писали:
А>>Здравствуйте, cpp, Вы писали:
cpp>>>Здравствуйте, fAX, Вы писали:
fAX>>>>Как быстро заполнить память повторяющимися 4-мя байтами. memset размножает младший байт. std::fill — относительно медленно...
cpp>>> cpp>>>по-моему так: cpp>>>
А>>В конце концов повспоминал ассемблер и приблизительно так и написал (кроме shr, он мне не нужен ). А>>Но большое спасибо!!!
DAS>__asm { DAS> mov eax, [your_four_bytes] DAS> mov edi, [you_array] DAS> xor ecx, ecx DAS> mov edx, [number_of_dwords] DAS>@foo: DAS> mov [edi+ecx*4], eax DAS> inc ecx DAS> cmp ecx, edx DAS> jne @foo DAS>}
DAS>а так — ещё быстрее
даже не так (мне тут товарищи подсказывают )
mov eax, [your_four_bytes]
mov edi, [you_array]
mov ecx, [number_of_dwords]
add edi, ecx
neg ecx
@foo:
mov [edi+ecx*4], eax
inc ecx
jne @foo
O !
... << RSDN@Home 1.0 beta 3 >>
Re[4]: Как быстро заполнить память повторяющимися 4-мя байта