![]() |
eXeL@B —› Программирование —› самый быстрый memcpy |
<< . 1 . 2 . |
Посл.ответ | Сообщение |
|
Создано: 15 февраля 2010 19:08 · Поправил: Vol4ok · Личное сообщение · #1 Протестируйте на предмет самой быстрой реализации memcpy - В нем содержится множество различных реализаций memcpy начиная от SSE заканчивая простым циклом. Заодно это отличный способ оценить скорость работы с памятью на компе. Результаты кидайте сюда, вместе с процом на котором тестировали. Мои результаты для Core2Duo 2.26 Code:
ЗЫ: если есть еще идеи для реализации быстрой memcpy, то кидайте сюда, если это будет актуально то включу в бэнчмэк. ![]() |
|
Создано: 16 февраля 2010 14:56 · Личное сообщение · #2 |
|
Создано: 16 февраля 2010 15:04 · Личное сообщение · #3 cppasm пишет: С каких соображений? Частота процессора может изменяться по ходу его работы. rdtsc следует использовать если мы хотим получить число тактов, а время надо мерять через QueryPerfomanceCounter, или на худой конец GetTickCount ----- PGP key ![]() |
|
Создано: 16 февраля 2010 15:20 · Личное сообщение · #4 |
|
Создано: 16 февраля 2010 15:25 · Поправил: Vol4ok · Личное сообщение · #5 cppasm пишет: С каких соображений? Одно на втором базируется. К тому что сказал ntldr могу добавить, что rdtsc - плох на мультипроцессорных системах, так как число тактов отличается на разных процессорах, непонятно, учитывал ли автор этой программы это обстоятельство. QueryPerfomanceCounter к rdtsc никакого отношения не имеет - он работает на основе системного таймера, встроенного в материнскую плату, который генерирует прерывания, через определенный интервал (на современных компах < 1 нс). ![]() |
|
Создано: 16 февраля 2010 16:54 · Личное сообщение · #6 |
|
Создано: 16 февраля 2010 17:09 · Личное сообщение · #7 |
|
Создано: 16 февраля 2010 17:31 · Личное сообщение · #8 software.intel.com/en-us/articles/measure-code-sections-using-the-enhanced-timer/ ----- PGP key ![]() |
|
Создано: 16 февраля 2010 19:16 · Личное сообщение · #9 Core2Duo E8500@3.7Ghz Code:
![]() |
|
Создано: 16 февраля 2010 20:45 · Личное сообщение · #10 |
|
Создано: 16 февраля 2010 20:47 · Личное сообщение · #11 |
|
Создано: 16 февраля 2010 21:00 · Личное сообщение · #12 |
|
Создано: 16 февраля 2010 21:51 · Поправил: kioresk · Личное сообщение · #13 Core i7 960 3.2 GHz Code:
![]() |
|
Создано: 18 февраля 2010 21:57 · Личное сообщение · #14 Итак подведу итоги. Просуммировав все представленные результаты получилась следующий статистика ![]() Лично для себя я сделал следующие выводы (исходя из удобства использования их в своих проектах) - самая удобная в использовании функа - movsd (и ее ntdll аналог RtlCopyMemory), плюсы в следующем + наличие соответствующей интринсик инструкции в компиляторе от МС + кросплатформенность (код с movsd будет работать как на х86 так и на х64, без дополнительных изощрений) + хорошие показатели скорости, при своей невероятной простоте. Ее можно использовать в проектах где скорость не является целью. Если же цель именно скорость то тут 2 фаворита реализация на MMX и SSE, как видно в большинстве случаев MMX работал быстрее, на самом деле я немного поэксперементировав, получил более быструю реализацию, которая сравнима с показателями MMX и даже превышает ее в ряде случаев (все желающий могут дополнительно это протестить в Но к сожалению они не так удобны в использовании как movsd, и не обладают кросплатформеностью, и требуют дополнительных изощрений с выравниванием. Реализация на MMX - может быть написана на интринсик инструкциях компилятора, но к сожалению не может работать под х64 системой. SSE реализация (в том виде который дает максимальные результаты) - не может быть написана интринсик - и неизбежно использование ассемблера в чистом виде. В моем случае использовался инлайн асм, но он не актуален для х64 бита систем, так что придется иметь дополнительный гимор и подшивать асм файлики для каждой платформы к проекту (в данном случае я подразумеваю использования мелкософтного компилятора). Однако те кто пользуются компилятором intel - думаю что SSE реализация на интринсик возможна, таким образом можно безболезнено вставлять эту реализацию в свои проекты не боясь проблем с компиляцией под разные платформы. Вот мои реализации обеих процедур (буфера должны быть выравнены по 64Б) MMX Code:
SSE (более крутая версия, а не та чтобы в первом тесте) Code:
Напоследок хотесь бы сказать немного "хорошего" о мелкософте который очередной раз лажанулся. Во первых это CRT. Дело в том что CRT реализация - использует SSE, но как видено в большинстве случаев movsd работает быстрее - и поэтому CRT реализация является неэффективной, и соответственно бесполезной. Какой смысл было выпендриваться SSE интрукциями, если они не дает оправданных результатов? Если бы они написали код который я представил выше - было бы куда круче. Также хочу отметить говеную реализацию интринсик инструкций, дело в том, что для того чтобы написать реализацию SSE на интринсик - не хватает всего одной интринсик инструкции - movntps (которая вцелом имеется но не в том виде котором нужно). Мало таго, "порадовала" их идиоцкая оптимизация - если откомпилять код на интринсик инструкциях - то они будут не в том порядке как в оригинале, нафига спрашивается переставлять? этот эффект можно наблюдать на суммарных результатах, как видно MMX реализация на асме в итоге выиграла, только потому что мелкософт влез со совей "оптимизацией" в интринсик реализацию, а код по совей сути идентичный. ЗЫ: спс ntldr за помощь в написании реализаций. ![]() |
|
Создано: 19 февраля 2010 14:21 · Личное сообщение · #15 ntldr пишет: Частота процессора может изменяться по ходу его работы. rdtsc следует использовать если мы хотим получить число тактов, а время надо мерять через QueryPerfomanceCounter, или на худой конец GetTickCount Ну и ахинея. В данном случае производительность надо мерять именно в тактах. Время здесь при чем? Если один код выполнится за 1000 тактов, а другой за 1100 - однозначно время выполнения первого кода будет меньше. Нет никаких причин думать, что при выполнении второго кода частота по каким то причинам будет выше и следовательно время выполнения меньше. ![]() |
|
Создано: 19 февраля 2010 14:49 · Личное сообщение · #16 Уважаемый spinz, меряйте производительность своего кода хоть в слонах и попугаях, но не учите нас жить. Да будет вам известно, что производительность копирования данных в памяти зависит не только от процессора, но и, как не странно, от скорости работы памяти, в следствии чего эффективность пакетного чтения удобнее считать в мегабайтах в секунду, а не непонятно как скачущих тактах процессора. К тому же, если речь заходит об измерении скорости работы параллельных алгоритмов, то растактовка становиться бесполезной чуть менее, чем полностью. spinz пишет: ет никаких причин думать, что при выполнении второго кода частота по каким то причинам будет выше и следовательно время выполнения меньше. Поздравляю, вы с громким плеском сели в лужу. Гуглите что такое Intel Turbo Boost, и не учите жить людей, занимающихся оптимизацией побольше вас. ----- PGP key ![]() |
|
Создано: 19 февраля 2010 15:14 · Личное сообщение · #17 ntldr пишет: Уважаемый spinz, меряйте производительность своего кода хоть в слонах и попугаях, но не учите нас жить. Да будет вам известно, что производительность копирования данных в памяти зависит не только от процессора, но и, как не странно, от скорости работы памяти, в следствии чего эффективность пакетного чтения удобнее считать в мегабайтах в секунду, а не непонятно как скачущих тактах процессора. К тому же, если речь заходит об измерении скорости работы параллельных алгоритмов, то растактовка становиться бесполезной чуть менее, чем полностью. Послушайте не надо подменять предмет дискусии. Невзирая на скорость памяти - если первый код закончит работу через 1000 тактов, а второй через 1100 - значит первый код закончит свое выполнение раньше. Посему rdtsc здесь самый точный способ замера производительности. ntldr пишет: Поздравляю, вы с громким плеском сели в лужу. Гуглите что такое Intel Turbo Boost, и не учите жить людей, занимающихся оптимизацией побольше вас. Про турбобуст я знаю не хуже вашего. Попробуйте мне объяснить - почему код1 и код2, выполняющиеся на одном ядре при прочих равных условиях, будут выполняться (хотя бы теоретически) при разных тактовых частотах? ![]() |
|
Создано: 19 февраля 2010 15:49 · Личное сообщение · #18 spinz пишет: Невзирая на скорость памяти - если первый код закончит работу через 1000 тактов, а второй через 1100 - значит первый код закончит свое выполнение раньше. Нет, не так, потому что частота процессора может меняться, нас же интересует абсолютное время. Представьте себе, что у нас быстрый проц, но медленная память, тогда чем выше частота процессора, тем больше тактов он ждет доставки данных из памяти, а значит код исполняется больше тактов, чем при меньшей частоте. Частота меняется, а значит мы меряем хрен знает что, и запросто может оказаться, что код исполняющийся больше тактов, на самом деле быстрее. spinz пишет: Попробуйте мне объяснить - почему код1 и код2, выполняющиеся на одном ядре при прочих равных условиях, будут выполняться (хотя бы теоретически) при разных тактовых частотах? Вот вам краткий список причин: 1 - Мы работаем в многозадачной ОС, а значит работа турбобуста зависит от нагруженности других ядер чужим кодом. Другие ядра нагружены - частота нашего ядра снижается. 2 - Есть такая штука, как гипертрединг, т.е. одно ядро может исполнять 2 потока одновременно. Представьте себе, что в то время, пока наш поток ждет доставки данных из памяти, другой поток исполняется на том же ядре, и турбобуст повышает его частоту. 3 - Процессор может уменьшать свою частоту при перегреве (тротлинг). На скорости работы с памятью это может не сказаться. Влияет даже в однозадачной среде. 4 - Процессор может засыпать на короткое время при низкой нагрузке, соответственно такты не считаются, пока идет ожидание получения данных. Особенно актуально для ноутбучных процессоров и влияет на растактовку даже в однозадачной среде. ----- PGP key ![]() |
|
Создано: 19 февраля 2010 16:09 · Личное сообщение · #19 Я указывал - "при прочих равных условиях", что исключает влияние вышеперечисленных причин. Про процы и память - я думал очевидно, что речь идет о замерах rdtsc на одной машине. Такты естественно не могут служить критерием быстродействия вообще, 100 тактов на пне1 и 200 тактов на коре-и7, немного разные вещи ))) Вообще подобные тесты производительности весьма неточно отражают ситуацию вне зависимости от методики измерения. Для точного замера надо исключить влияние ОС и многопроцовости. Те же мегабайты в секунду могут быть совсем другими, когда другое ядро к примеру имеет кучу промахов кэша. ![]() |
|
Создано: 19 февраля 2010 16:22 · Личное сообщение · #20 spinz пишет: Я указывал - "при прочих равных условиях", что исключает влияние вышеперечисленных причин. Ну так мы работаем с реальным железом и софтом, и хотелось бы всегда получать корректные результаты. spinz пишет: Про процы и память - я думал очевидно, что речь идет о замерах rdtsc на одной машине. Речь идет об одной машине. Допустим, что у меня быстрый проц и медленная память (пример - платформа на Core i5 с одной планкой памяти). Мне хотелось бы померять как быстро идет копирование памяти, а не сколько пустых тактов простаивает проц при доступе к ней. spinz пишет: Для точного замера надо исключить влияние ОС и многопроцовости. Я придерживаюсь точки зрения, что код следует оптимизировать под исполнение в реальной среде, где он потом будет применяться, а не под сферический процессор в вакууме. Поэтому я меряю такты только для кода, который позволяет все свои данные целиком разместить в кэше. В этом случае я делаю цикл на пару сотен тысяч итераций и выбираю наименьшее число тактов по всем замерам. Если же велико влияние памяти, то надо мерять время. ----- PGP key ![]() |
|
Создано: 19 февраля 2010 17:12 · Поправил: cppasm · Личное сообщение · #21 ntldr пишет: Мне хотелось бы померять как быстро идет копирование памяти, а не сколько пустых тактов простаивает проц при доступе к ней. Так это и будет тот самый сферический конь. Время копирования памяти включает в себя время ожидания доступа к ней. Какой смысл мерять только скорость копирования, если при реальном применении будет влиять и задержка доступа к памяти? Если исключить влияние изменения тактовой частоты и привязать поток к одному ядру, rdtsc будет давать то же измерение времени, только в других единицах. ![]() |
|
Создано: 19 февраля 2010 17:34 · Личное сообщение · #22 Вспомните недавнюю тему, где была программа для сопряжения с девайсом на ком порту управляющая форсунками. На мобильных платформах есть конкретный баг с замером через rdtsc. Ну и вообще, что меряется? Копирование участка памяти, то есть важно знать сколько данных можно скопировать за определенное время, а это мб/сек... ![]() |
|
Создано: 19 февраля 2010 18:19 · Личное сообщение · #23 spinz,cppasm моей целью было найти самую быструю реализацию именно по времени, когда я пишу программу мне важно не сколько тактов она сожрет, а сколько времени будет работать, поэтому я выбираю именно те величины которые имеют для меня значение. Тоже касается и условий тестирования, они должны быть аналогичны тем, в которых потом будет выполнятся мой код. И еще, крайне бессмысленно пытаться учить людей, что и как им делать, особенно в тех случаях когда об этом не просят и очень-очень особенно когда эти люди четко знают как им лучше это сделать. Если вас так сильно интересует измерение производительности в тактах, то было бы куда полезней сесть и написать свой бэнчмэк, протестировать и представить результаты, а не разводить бестолковый флуд. ![]() |
|
Создано: 19 февраля 2010 18:35 · Личное сообщение · #24 cppasm пишет: Так это и будет тот самый сферический конь.Время копирования памяти включает в себя время ожидания доступа к ней. Видимо вы пропустили предыдущие посты. Если мне нужно знать время - я меряю время. Если нужна растактовка - меряю такты. Некоторые не понимают, что это разные, нетривиально коррелирующие вещи. cppasm пишет: Если исключить влияние изменения тактовой частоты Можно отключить гипертрединг, турбобуст, энергосбережение, и мерять исключительно из-под доса, но зачем? Если в ТЗ проекта не написано "сделать только так, и никак иначе", то я волен выбирать оптимальные способы под конкретную задачу. ----- PGP key ![]() |
|
Создано: 19 февраля 2010 20:16 · Поправил: cppasm · Личное сообщение · #25 Vol4ok пишет: И еще, крайне бессмысленно пытаться учить людей, что и как им делать, особенно в тех случаях когда об этом не просят и очень-очень особенно когда эти люди четко знают как им лучше это сделать. По-моему никто никого не учил. Хотя вам виднее. А если так нравится придалбываться к мелочам, то я тоже умею ![]() Vol4ok пишет: QueryPerfomanceCounter к rdtsc никакого отношения не имеет - он работает на основе системного таймера, встроенного в материнскую плату, который генерирует прерывания, через определенный интервал (на современных компах < 1 нс). Период в 1нс это тактовая частота 1/10^-9=10^9Hz=1GHz Если прерывания будут сыпать с такой частотой, система только их и обрабатывать будет. У HPET (High Precision Event Timer) частота максимальная 10MHz. Vol4ok пишет: Если вас так сильно интересует измерение производительности в тактах, то было бы куда полезней сесть и написать свой бэнчмэк, протестировать и представить результаты, а не разводить бестолковый флуд. Результаты будут аналогичные (в относительных величинах). ToBad пишет: Вспомните недавнюю тему, где была программа для сопряжения с девайсом на ком порту управляющая форсунками. На мобильных платформах есть конкретный баг с замером через rdtsc. Нету там никаких багов. На мобильных платформах широко используется изменение тактовой частоты в зависимости от нагрузки, отсюда и проблемы. Мерять надо нормально, понимая что меряешь. А прога та не работала, потому что нечего задержки делать вида for(i=0;i<0x100000;i++); Ясно что на разных процессорах (разных поколениях) время выполнения будет очень разное. Вообще в статье на которую ссылку давал HiEndsoft всё правильно написано, точнее не скажешь: Некоторые используют в качестве таймера команду RDTSC, считывающую показания внутреннего счетчика процессора, каждый такт увеличивающегося на постоянную величину (как правило, единицу). Для профилировки машинного кода она подходит на ура, но вот на роль беспристрастного метронома уже не тянет. Некоторые APCI-контроллеры динамически изменяют частоту процессора или усыпляют его в паузах между работой для лучшего охлаждения. Как следствие - непосредственное преобразование процессорных тактов в истинное время оказывается невозможным. ![]() |
|
Создано: 19 февраля 2010 21:54 · Поправил: Vol4ok · Личное сообщение · #26 cppasm пишет: По-моему никто никого не учил. Хотя вам виднее. тогда я не понимаю вашей цели и что вы пытаетесь тут всем доказать, вы пытаетесь доказать что мои результаты не состоятельны? или хотите мне предложить написать реализацию на rdtsc? я думаю очевидно, что писать реализацию на rdtsc я не буду, и мои результаты меня устраивают, тех кого не устраивают пишите свои тесты. cppasm пишет: А если так нравится придалбываться к мелочам, то я тоже умею период в 1нс это тактовая частота 1/10^-9=10^9Hz=1GHz Если прерывания будут сыпать с такой частотой, система только их и обрабатывать будет. У HPET (High Precision Event Timer) частота максимальная 10MHz. я говорил это на основании показателя частоты QueryPerformanceFrequency, который на моем компе равна 2 256 360 000, откуда один период составляет 4,43e-10с. Для моих измерений достаточно точности даваемой QueryPerformanceCounter даже если он будет с частотой 100KHz, на худой конец это легко можно проверить увеличив размер буфера - в моем случае результаты оставались прежними. Я не могу понять что вы мне этим хотели показать? Ваше умение "придалбываться к мелочам" не соответствует содержанию данной темы. Ввиду перехода обсуждения в бесцельный флуд, я закрываю тему. Топикстартер все что хотел выяснил, всем кто принимал участие в этом выражается благодарность. ![]() |
<< . 1 . 2 . |
![]() |
eXeL@B —› Программирование —› самый быстрый memcpy |
Эта тема закрыта. Ответы больше не принимаются. |