Эта тема поднималась на форуме и ни раз, но до того, что я недавно придумал, дело видимо не доходило. Для того, чтобы эффективно копировать память в ЯВУ нередко используется встроеный ассемблер, но даже при этом работа с массивами порой получается значительно медленнее, чем хотелось бы.
А вот собственно вопрос: как быстро пересылать большие массивы данных??. В masm32 v8.2 я нашел только memfill() и memcopy(). Думаю, их исходники (или что-то похожее) форумчане видели не раз, а потому приводить их не имеет смысла. В качестве оптимизации можно предложить пересылать по нескольку двойных слов за цикл или грамотное исползование второго конвеера (чтобы исполнялись одновременно две команды). Но это не панацея. Я подумал, а что если для пересылки использовать не только целочисленные комманды, но и FPU, ведь последний может обрабатывать числа длиной по 10 байт (или можно 8) за команду (а не по 4). Или можно придумать симбиоз трех конвееров, чтобы за каждый цикл пересылать одновременно еще больще данных. Остаток можно копировать обычными методами. Думаю, не смотря на то, что FPU работает медленее, при достаточно больших массивах игра стоит свеч. Пока нет времени и желания это реализовывать. Если кто-то это уже сделал, то может дадите исходнячок или напишитевариант этой функции. А вообще в ближайшие дни постораюсь этим заняться.
std::copy + IntelC 8.1 будет быстрее всякого memcpy
2 Da1t0NIC
>>грамотное исползование второго конвеера (чтобы исполнялись одновременно две команды)
на дворе 2005 год, U,V умерли со времён первых пентиумов
вообще CyberZX дал тебе самый лучший совет
лично я пользуюсь rep movsd
В Doom3 SDK есть реализация этой функции с использованием MMX, я правда не пробовал, возможно тоже довольно быстрая реализация
имхо rep movs рулит :)
CyberZX
>std::copy + IntelC 8.1 будет быстрее всякого memcpy
Я ассемблеровщик и мне доставляет удовольствие делать все ручками:).
Neill
>В Doom3 SDK есть реализация этой функции с использованием MMX, я правда не
>пробовал, возможно тоже довольно быстрая реализация
MMX это почти тот же FPU. Команды другие но работают с теми же регистрами. В любом случае ничего кроме загрузить по такому-то и выгрузить по такому-то адресу здесь не требуется. Жаль, оказывается не первый кто до этого додумался:). Вообще же, если игра достаточно требовательная и заранее известно, что в нее можно будет играть лишь на Pentium 3 или 4, то выгоднее использовать расширение SSE и писать сразу по 16 байт, а еще лучше объединить это с FPU и целочисленными вычислениями.
_UnSeen_
>имхо rep movs рулит :)
А вот этим я и предлагаю копировать остаток
2 Da1t0NIC
>>Я ассемблеровщик и мне доставляет удовольствие делать все ручками:).
тебя здесь скоро вылечат
Da1t0NIC
Перед изобретением собственных методов советую почитать:
http://redvip.homelinux.net/varios/AMD/AMD_block_prefetch_paper.pdf
Da1t0NIC
>Эта тема поднималась на форуме и ни раз, но до того, что я недавно придумал, дело >видимо не доходило.
вот и читай те темы, нам все написано, зачем создавать еще одну.
p.s. Всем:
как отключить VSync, как найти пересечение того с этим, что лучше Dx или OpenGL, как загрузить bmp файл. Знакомо? :))))))))))))
Da1t0NIC
>Я ассемблеровщик
ну значит должен понимать, что battle neck при копировании памяти это не скорость выполнения команд процессора, а сама память, которая является по сути штука весьма медленная. по-этому не стоит заниматься оптимизацией копирования памяти в общем случае, современные компиляторы очень хорошо с оптимизируют тот же std::copy. Хотя это не значит, что нельзя ускорить процесс копирования памяти, просто нельзя оптимизировать для общего случая.
JokerR
>на дворе 2005 год, U,V умерли со времён первых пентиумов
Кто тебе такую чушь сказал?
>лично я пользуюсь rep movsd
Ну если узать асм, что бы затормозить немного игру, то да...
2 Akad
>>Кто тебе такую чушь сказал?
Агнер Фог ночью шептал, когда мне юзергуайд 4-го пня снился
>>Ну если узать асм, что бы затормозить немного игру, то да...
конечно, для чего же ещё
Akad
Всё правильно он сказал. U и V pipe были в Pentium. В Pentium-Pro/P2/P3... (P6-архитектура) используется 1 конвеер, но несколько исполняющих блоков.
JokeR
О, уже ответил ;)
кстати, забираю свои слова про memcpy назад :)
современные компиляторы воспринимают memcpy как интристик, так что это наиболее быстрая реализация копирования памяти. вот например такую конструкцую
memcpy(out_buffer.get( ), in_buffer.get( ), buffer_size);
vc7.1 заменил на
mov esi,dword ptr [ebx] mov edi,dword ptr [ebx+4] mov ecx,1900000h rep movs dword ptr [edi],dword ptr [esi]
хотя
std::copy(in_buffer.get( ), in_buffer.get( ) + buffer_size, out_buffer.get( ));
он заменил вызовом вручную оптимизированой функции __imp__memmove из memcpy.asm, которая даже при копировании блока 100 мегабайт, оказалась медленнее, чем простой rep movs.
сейчас проверю что сделает интеловский компилятор
Da1t0NIC
>Я ассемблеровщик и мне доставляет удовольствие делать все ручками:).
Respectz!
Тема в архиве.