Re[5]: Как быстро обнулить массив?
От: mokc0der  
Дата: 19.08.04 12:04
Оценка:
Здравствуйте, OpenGL, Вы писали:

OGL>mmx,(3dnow, 3dnow+) sse, sse2 самое быстрое последнее 128 бит за цикл.

не возможности протестировать sse2, но разницы между обнулением через mmx(64bit) и xmm(128bit) нет ни какой. Это протестировано
Re[2]: Как быстро обнулить массив?
От: MShura  
Дата: 19.08.04 12:20
Оценка:
Здравствуйте, zix, Вы писали:

zix>Здравствуйте, Alfarn, Вы писали:


A>>Есть массив DWORD'ов. Нужна максимально быстрая процедура для его обнуления. memset не предлагать!


zix>Я думаю, быстрее чем команда STOS ничего найти не удастся...


Крис Касперски описывал алгоритм, который позволяет сделать функции memset,memcpy быстрее. Для этого надо знать про кэши. Суть в том, чтобы периодически обращаться к памяти, которая будет обрабатываться позже, а затем продолжать операции.
В итоге к тому моменту когда очередь дойдет до той памяти, её содержимое уже будет в кэше.
Re: Как быстро обнулить массив?
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 20.08.04 03:53
Оценка:
Несколько стратегий (можно комбинировать):
1) находим точку вычищаемого блока, начинающуюся на границе N байт (где N — сколько байт будем чистить одной инструкцией), и чистим начиная с нее (т.е. соблюдая выравнивание); остальное дотираем вручную.
2) возможно, поможет TLB priming. Вообще говоря, этот прием предназначен скорее для чтения данных, но, может статься, ускорит и запись. Речь идет о том, чтобы каждый раз перед переходом записи на границу новой страницы (4К) заранее обращаться к одному элементу на этой странице, чтобы ее данные успели подгрузиться в TLB (Transaction Lookaside Buffer).
3) ну и, конечно, если доступен набор команд MMX, можно юзать MMX-инструкции, а еще лучше SIMD 2. На P4 инструкция MOVAPS ворочает по 128 бит за одну операцию. Если так роскошествовать не получается, можно пользоваться MOVQ. Между прочим, MOVAPS требует 16-байтного выравнивания точки записи.

Кроме того, есть еще как минимум 2 интересных подхода.
I) воспользоваться страничной адресацией: замапить на весь требуемый диапазон логического адресного пространства одну и ту же (или несколько) страницу памяти, которую предварительно зануляем. Есть некоторые шансы (не проверял), что VirtualAlloc, например, 32 страниц будет работать быстрее, чем заполнение нулями 32*4=128 Кб данных. Режим защиты можно указать PAGE_WRITECOPY — тогда при любых изменениях этой области памяти будут создаваться новые физические страницы.
II) пропатчить процесс, обрабатывающий данные, так, чтобы он их вообще не читал, а сразу полагал равными 0. По окончании нужной операции можно пропатчить обратно. Проблема, которая видна сразу же — если в том процессе работает несколько потоков, одновременно обрабатывающих одним кодом разные области данных, будет плохо.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: Как быстро обнулить массив?
От: sSerge  
Дата: 20.08.04 07:42
Оценка:
Здравствуйте, Alfarn, Вы писали:

A>Есть массив DWORD'ов.

A>Нужна максимально быстрая процедура для его обнуления. memset не предлагать!

Думаю, альтернативы для memset (или его клонов) просто нет.

Что касается ассемблера, то самая быстрая получается инструкция movq.
В принципе, то как следует работать с кэшем вот здесь.
Пример, правда, для AMD и для memcpy. Но я переделывал его для memset и для memcmp.
Работает и на Intel и на AMD.
С уважением, Сергей.
Re[2]: Как быстро обнулить массив?
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 20.08.04 10:21
Оценка:
S>Что касается ассемблера, то самая быстрая получается инструкция movq.
Точно не MOVAPS и иже с ней? Разрядность-то поболее будет.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: Как быстро обнулить массив?
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 23.08.04 10:45
Оценка:
Все оказалость намного интереснее. CreateFileMapping работает очень быстро (7-8 тысяч тактов на моем Athlon64) даже при выделении блоков памяти порядка 64Мб — и при этом создаваемые страницы считаются зануленными. Т.е. сама подготовка памяти происходит моментально. Правда, можно проиграть при ее реальном использовании

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[3]: Как быстро обнулить массив?
От: Alex Alexandrov США  
Дата: 27.08.04 19:33
Оценка:
Здравствуйте, MShura, Вы писали:

M> Здравствуйте, zix, Вы писали:

M>
zix>> Здравствуйте, Alfarn, Вы писали:
M>
A>>> Есть массив DWORD'ов. Нужна максимально быстрая процедура для его
A>>> обнуления. memset не предлагать!
M>
zix>> Я думаю, быстрее чем команда STOS ничего найти не удастся...
M>
M> Крис Касперски описывал алгоритм, который позволяет сделать функции
M> memset,memcpy быстрее. Для этого надо знать про кэши. Суть в том, чтобы
M> периодически обращаться к памяти, которая будет обрабатываться позже, а
M> затем продолжать операции. В итоге к тому моменту когда очередь дойдет
M> до той памяти, её содержимое уже будет в кэше.

Непонятно. Если ты последовательно забиваешь память нулями, то каждая линейка кэша будет ровно один раз прочитана и ровно один раз сброшена обратно — чего хитрить-то?

-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.9 beta
It's kind of fun to do the impossible (Walt Disney)
Re[4]: Как быстро обнулить массив?
От: Alex Alexandrov США  
Дата: 27.08.04 19:35
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:


[Sorry, skipped]

M>> Крис Касперски описывал алгоритм, который позволяет сделать функции

M>> memset,memcpy быстрее. Для этого надо знать про кэши. Суть в том, чтобы
M>> периодически обращаться к памяти, которая будет обрабатываться позже, а
M>> затем продолжать операции. В итоге к тому моменту когда очередь дойдет
M>> до той памяти, её содержимое уже будет в кэше.
AA>
AA> Непонятно. Если ты последовательно забиваешь память нулями, то каждая
AA> линейка кэша будет ровно один раз прочитана и ровно один раз сброшена
AA> обратно — чего хитрить-то?
AA>
AA> -- Всего хорошего!
AA> -- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com

Хотя стоп — если имелась в виду инструкция PREFETCH, то нормально — действительно поможет.

-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.9 beta
It's kind of fun to do the impossible (Walt Disney)
Re[5]: Как быстро обнулить массив?
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 28.08.04 06:23
Оценка:
Здравствуйте, Alex Alexandrov, Вы писали:

AA>Хотя стоп — если имелась в виду инструкция PREFETCH, то нормально — действительно поможет.


А я вот не думаю, что поможет. Что проку от предвыборки, если нам надо не читать, а писать данные? Тут наоборот должна помочь именно опережающая запись одной ячейки в следующую страницу. Потому что 1) в отличие от чтения, код не ждет завершения операции (из-за чего, видимо, и ввели PREFETCH), 2) выполняется TLB priming. А больше вроде как ничего и не надо.

А чем вас, господа, не устроило мое предложение поизвращаться с файл-маппингом?

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[6]: Как быстро обнулить массив?
От: Alex Alexandrov США  
Дата: 28.08.04 09:51
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM> Здравствуйте, Alex Alexandrov, Вы писали:

SM>
AA>> Хотя стоп — если имелась в виду инструкция PREFETCH, то нормально -
AA>> действительно поможет.
SM>
SM> А я вот не думаю, что поможет. Что проку от предвыборки, если нам надо
SM> не читать, а писать данные? Тут наоборот должна помочь именно
SM> опережающая запись одной ячейки в следующую страницу. Потому что
SM> 1) в отличие от чтения, код не ждет завершения операции (из-за чего,
SM> видимо, и ввели PREFETCH), 2) выполняется TLB priming. А больше вроде
SM> как ничего и не надо.
SM>
SM> А чем вас, господа, не устроило мое предложение поизвращаться с
SM> файл-маппингом?
SM>
SM> Slicer

Политика записи по умолчанию — write-back. Т.е. происходит запись в кэш и немедленный возврат, а в основную память данные записываются асинхронно. Однако кэш и для чтения, и для записи один, поэтому перед записью линейка должна быть прочитана из памяти. PREFETCH помогает это сделать заранее.
Насчет TLB. Кэширование и трансляция адресов — вещи ортогональные. Одно другому не мешает. Только опять же упредить трансляцию адресов можно только в случае наличия аналога PREFETCH для TLB. Т.е. что-то типа PREFETCHTLB. Поскольку в противном случае (попытки упреждающей записи одной ячейки в следующую страницу) при последовательном проходе (мы же рассматриваем обнуление, так?) выгоды не будет. Какая разница, произойдет TLB_MISSED penalty на твоей упреждающей записи или на первой записи при реальном переходе на следующую страницу...

-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.9 beta
It's kind of fun to do the impossible (Walt Disney)
Re[7]: Как быстро обнулить массив?
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 28.08.04 10:10
Оценка:
AA>Политика записи по умолчанию — write-back. Т.е. происходит запись в кэш и немедленный возврат, а в основную память данные записываются асинхронно. Однако кэш и для чтения, и для записи один, поэтому перед записью линейка должна быть прочитана из памяти. PREFETCH помогает это сделать заранее.
Хм, надо обратиться к первоисточникам. На самом деле, идея та, что микрооперации инструкции записи начнут выполнение в одном из конвейеров, а т.к. от результата записи никакие другие инструкции кода не зависят, то можно сразу же запускать последующие команды кода. Но это что касается "deeply pipelined" процессоров (как P4), а вот для остальных, может, и не так.

AA>Насчет TLB. Кэширование и трансляция адресов — вещи ортогональные. Одно другому не мешает. Только опять же упредить трансляцию адресов можно только в случае наличия аналога PREFETCH для TLB. Т.е. что-то типа PREFETCHTLB. Поскольку в противном случае (попытки упреждающей записи одной ячейки в следующую страницу) при последовательном проходе (мы же рассматриваем обнуление, так?) выгоды не будет. Какая разница, произойдет TLB_MISSED penalty на твоей упреждающей записи или на первой записи при реальном переходе на следующую страницу...

Ну, см. предыдущий ответ — penalty на данную операцию записи ведь не вызовет полный останов всех конвейеров.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[8]: Как быстро обнулить массив?
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 28.08.04 10:20
Оценка:
SM>Ну, см. предыдущий ответ — penalty на данную операцию записи ведь не вызовет полный останов всех конвейеров.
А, не то объяснял )) В смысле — так застрянет одна операция, а если выполнить первый доступ к странице уже при последовательной записи, застрянут столько инструкций, сколько успеет набиться в конвейеры до окончания загрузки в TLB. Хотя, с другой стороны, может, ты и прав — все равно, вроде бы (не уверен) микрооперации доступа к памяти обслуживает всего один модуль процессора, так что ждать в любом случае придется всем последующим пишущим инструкциям.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re: Как быстро обнулить массив?
От: Remint_Ubere Россия  
Дата: 28.08.04 13:27
Оценка:
Здравствуйте, Alfarn, Вы писали:

A>Есть массив DWORD'ов. Нужна максимально быстрая процедура для его обнуления. memset не предлагать!


Раз DWORD то скорее всего под виндой , тогда удобно юзать эти:

void ZeroMemory(
PVOID Destination,
SIZE_T Length
);


PVOID SecureZeroMemory(
PVOID ptr,
SIZE_T cnt
);

Первая это по сути макро (может оптимизироваться по разному при компиляции — подставлять конкретные значения и т.д.).
Вторая — функция (inline).
Re: Как быстро обнулить массив?
От: Alex Alexandrov США  
Дата: 28.08.04 18:14
Оценка: +1
Здравствуйте, Alfarn, Вы писали:

A> Есть массив DWORD'ов. Нужна максимально быстрая процедура для его

A> обнуления. memset не предлагать!

Еще, кстати, можно ускорить обнуление путем его отложения на некоторое время. Суть простая: памяти делается VirtualProtect(PAGE_NOACCESS), потом ловим исключения Access Violation и если ошибка доступа произошла на странице из нашего массива — делаем VirtualProtect(PAGE_READWRITE), обнуляем страницу и возвращаем EXCEPTION_CONTINUE_EXECUTION. Особенно может улучшить производительность, если не факт, что вся обнуляемая память будет задействована в будущем. Минусы — код обнуления размазывается по нескольким местам.

-- Всего хорошего!
-- Alex Alexandrov, e-mail: alex_alexandrov@fromru.com
Posted via RSDN NNTP Server 1.9 beta
It's kind of fun to do the impossible (Walt Disney)
Re[6]: Как быстро обнулить массив?
От: OpenGL  
Дата: 29.08.04 08:25
Оценка:
Здравствуйте, mokc0der, Вы писали:

M>Здравствуйте, OpenGL, Вы писали:


OGL>>mmx,(3dnow, 3dnow+) sse, sse2 самое быстрое последнее 128 бит за цикл.

M>не возможности протестировать sse2, но разницы между обнулением через mmx(64bit) и xmm(128bit) нет ни какой. Это протестировано

Дело в том что я имел ввиду параллельное выполнение и использование U V конвееров тогда разница будет заметна.
Там за такт два mov можно сделать!
Re: Как быстро обнулить массив?
От: Аноним  
Дата: 29.08.04 10:02
Оценка:
Здравствуйте, Alfarn, Вы писали:

A>Есть массив DWORD'ов. Нужна максимально быстрая процедура для его обнуления. memset не предлагать!


Можно попробовать посмотреть на результаты компилятора Intel C Compiler. Я предполагаю использование /O3. При том, что компилятор может вычислить размер обнуляемой памяти на этапе компиляции он генерирует примерно следующий код. Первой инструкцией он обнуляет 1 из xmm регистров (SSE инструкции), а затем просто выполняет mov за movом в память, двигаясь от младших адресов к старшим. Таких movов лично я видел пару страниц. Учитывая, что обнуление памяти — частая задача, я думаю, что такое поведение специально запрограммировано и даёт наилучшие результаты. Естествено для P4. Будет ли такой код оптимальным для Athlon неизвестно.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.