Привет. Предистория. Есть один и тот же алгоритм написанный на MMX и на обычных командах. Захотелось померять прирост производительности, воспользовался RDTSC. Вроди всё как положено, поставил процессу REAL_TIME_PROIRITY_CLASS, потоку поставил THREAD_PROIRITY_TIME_CRITICAL, поставил AffinityMask для потока только на один процессор и вперёд. Делаем 1000000 замеров в цикле и потом вычисляем прирост. И вот тут начинаются чудеса. Сразу скажу что результаты повторяемые, т.е. это не случайные косяки с RDTSC. На однопроцессорной машине всё даёт ожидаемые результаты - ~38% прирост. А на многопроцессорной (либо двуядерной, либо просто с HyperThreading) получается ерунда. По замерам прироста нет совсем. Но! Если нагрузить остальные ядра, то результат получается примерно как на однопроцессорной машине. Т.е. если для каждого ядра создать поток в котором делать просто jmp $, результаты такие же как и на однопроцессорной машине. И это при том, что поток в котором выполняется измеряемый код жёстко привязан к одному ядру, это к примеру в диспетчере задач видно. Вопрос в том что это за приколы такие? Как нагрузка на одно ядро может влиять на производительность другого? Причём влиять по разному - производительность MMX падает незначительно, а производительность обычных команд типа add/sub/imul - значительно? Кто что думает по этому поводу?
Ну много факторов влияния возможно. Много различных состояний производительности процессора. ОС может шалить (видел такие KB в которых фиксились другие KB в которых были ошибки с состояниями производительности) http://support.microsoft.com/kb/896256 http://support.microsoft.com/kb/330512
Нет, не стоит... Да и какая разница? Если на ядре выполняется поток с приоритетом реального времени, то оно просто не может в энергосберегающем режиме находиться. Что интересно - если запускать программу из-под VTune то и замеры программы, и результаты VTune получаются такими же как при загрузке всех ядер.
AFAIK HyperThreading не отдлельное ядро, а так, хитро-жёппый out of order execution... На реальном dual core что происходит с выставленой affinity и без?
Ну это не out of order execution... Там просто нету полноценного ядра, но некоторые исполнительные блоки дублируются. На серваке с двумя Intel Xeon Dual Core (т.е. 2 процессора по два ядра) то же самое. При нагрузке на все ядра результаты одни, при нагрузке только на ядро на котором выполняется замеряемый код - другие (я склонен считать что неправильные, на одноядерной машине результаты получаются как на многоядерной с полностью загруженными ядрами)...
Без дополнительных потоков пробовал - результат написан выше. А без установки affinity mask (без привязки к ядру) пробовать смысла нету. ОС тогда гипотетически может мой поток перекидывать между ядрами, а у каждого из них RDTSC считает независимо, т.е. что я в итоге намеряю непонятно.
cppasm Помойму вы противоречите сами себе. Еще раз проверьте все и выложите результаты. По моим мыслям HyperThreading - должен работать так. Если на одном ядре работает твой код на другом jmp $ то тут должны наблюдаться такиеже результаты как и на одно ядерном. Без использования второго ядра HyperThreading будет тормазить и система будет работать медленее. Если загрузить оба ядра то прирост несколько процентов. Причем я считаю если на одно ядро поместить код с MMX а надругую обычные команды то прирост будет больше. А вот на настоящем двух ядерном такого недолжно наблюдаться.
cppasm Вот именно, что "гипотетически". Если алгоритм позволяет, то лучше не накручивать офигенные циклы, а ноборот стремиться уложиться в микросекунды, тогда и вероятность переключения потока будет достаточно мала. А для отбраковки случайных "сбоев" достаточно делать серию из 8-10 проходов и брать только повторяемые результаты Pavia В принципе тоже может, если код интенсивно работает с памятью (видимо так оно и есть, раз речь об MMX). В этом случае пустой цикл на втором ядре гарантированно не лезет в память, не засоряет общий кэш L2, и не требует доп.проверок когерентности L1
Откуда дровишки ? У AMD точно разные и работают на частоте своего ядра, и соотв-но могут разбегаться при изменении частоты. У Intel скорее всего тоже разные, но работают синхронно на фикс.частоте и поэтому не разбегаются (или скажем так - не должны
Нет, не противоречу. На одноядерной машине прирост 38%. На двуядерной мой код запускается только на одном ядре. Если остальные ядра не трогать - то прироста нет совсем, т.е. время выполнения с MMX и без примерно одинаково. Если же пригрузить остальные ядра, то скорость MMX кода практически не падает, а скорость обычного кода падает сильно - и получаем те же 38% прироста у MMX. Я думал может с кешем ерунда какая-то. Но у двуядерных процессоров ведь у каждого ядра свой кеш? Если кому интересно могу выложить две тестовые программки, погоняете у кого есть двуядерные процессоры.
В смысле? От какой системы? Да, для любых подойдут, даже для однопроцессорных. В архиве два файла - speedcmp_st.exe и speedcmp_mt.exe, соответственно однопоточная и многопоточная версия. У меня результаты такие. Однопоточная: Многопоточная: Ещё раз подчеркну, что в многопоточной версии замеряемый код всё равно работает в одном потоке, в остальных потоках просто пустой цикл while(loop_thread); И всё равно на P4 MMX как-то туго работает. Проверял ещё на Celeron D и на AMD Duron - прирост намного выше.
в обоих ~20%. Тестил раз 10. Q6600 Не пробовал после установки аффинита делать Sleep(0) ? Code (Text): =============================== Performing ALGO speed test... =============================== Execution time (fix) -> 57217941 clocks Execution time (mmx) -> 45160083 clocks 21% speedup. =============================== Performing ALGO speed test... =============================== Execution time (fix) -> 58734189 clocks Execution time (mmx) -> 45895005 clocks 21% speedup.
Пробовал, не помогает. Погонял тут ещё - похоже HyperThreading такие чудеса творит. На AMD Opteron Dual-Core (2 CPU по два ядра) результаты в обоих вариантах идентичны. На Intel Xeon (2 CPU одноядерных с HyperThreading) - эффект наблюдается, разброс есть ~15%