Я использую следующий код для профилирования своих операций для оптимизации циклов процессора, выполняемых в моих функциях.
static __inline__ unsigned long GetCC(void) { unsigned a, d; asm volatile("rdtsc" : "=a" (a), "=d" (d)); return ((unsigned long)a) | (((unsigned long)d) << 32); }
Я не думаю, что это лучше, поскольку даже два последовательных звонка дают мне разницу в «33». Какие-либо предложения ?
Я лично считаю, что команда rdtsc великолепна и полезна для множества задач. Я не думаю, что использование cpuid необходимо для подготовки к rdtsc. Вот как я рассуждаю вокруг rdtsc:
Что касается вопроса о точности счетчика времени, я бы сказал, что если предположить, что tsc на разных ядрах синхронизированы (что является нормой), возникает проблема дросселирования процессора в периоды низкой активности для снижения потребления энергии. При тестировании всегда можно блокировать функциональность. Если вы выполняете инструкцию на частоте 1 ГГц или 10 Мгц на одном процессоре, прошедшее количество циклов будет таким же, даже если первое завершено в 1% времени, которое было передано последнему.
Попытка подсчета циклов индивидуального выполнения функции на самом деле не является правильным способом. Тот факт, что ваш процесс может быть прерван в любое время, наряду с задержками, вызванными промахами кеша и неверными предсказаниями отрасли, означает, что может быть значительное отклонение в количестве циклов, взятых от вызова к вызову.
Правильный путь:
clock()
), принятыми для большого количества вызовов функции, а затем усредните их; или же Кстати, вам нужно выполнить сериализующую инструкцию перед RDTSC
. Обычно используется CPUID
.
Вы на правильном пути 1 , но вам нужно сделать две вещи:
cpuid
перед rdtsc
чтобы очистить конвейер процессора (делает измерение более надежным). Насколько я помню, clobbers регистрируется от eax
до edx
. gettimeofday
(Linux, так как вы не упомянули о платформе) и rdtsc
. Затем вы можете узнать, сколько времени занимает каждый тик TSC. Другим соображением является синхронизация TSC между процессорами, поскольку каждое kernel может иметь свой собственный счетчик. В Linux вы можете увидеть его в /proc/cpuinfo
, ваш CPU должен иметь флаг constant_tsc
. У большинства новых процессоров Intel, которые я видел, есть этот флаг. 1 Я лично нашел, что rdtsc
является более точным, чем системные вызовы, такие как gettimeofday()
для мелкозернистых измерений.
Другое дело, что вам может потребоваться беспокоиться, если вы работаете на многоядерном компьютере, программа может быть перенесена на другое kernel, которое будет иметь другой счетчик rdtsc. Тем не менее, вы можете связать процесс с одним kernelм с помощью системного вызова.
Если бы я пытался измерить что-то вроде этого, я бы, вероятно, записывал метки времени в массив, а затем возвращался и рассматривал этот массив после того, как код, который был проверен, был завершен. Когда вы изучаете данные, записанные в массив временных меток, вы должны иметь в виду, что этот массив будет полагаться на кэш ЦП (и, возможно, подкачки, если ваш массив большой), но вы можете предварительно отбирать или просто учитывать это при анализе данные. Вы должны увидеть очень правильную временную дельта между отметками времени, но с несколькими шипами и, возможно, несколькими провалами (вероятно, от перехода к другому ядру). Дельта регулярного времени, вероятно, является вашим лучшим измерением, поскольку он предполагает, что никакие внешние события не влияли на эти измерения.
При этом, если код, который вы сравниваете, имеет неправильные шаблоны доступа к памяти или время выполнения или зависит от системных вызовов (особенно связанных с IO), тогда вам будет трудно отделить шум от данных, которые вас интересуют.
TSC не является хорошим показателем времени. Единственной гарантией, которую CPU делает в TSC, является то, что она monoтонно возрастает (т. RDTSC
Если вы RDTSC
один раз, а затем повторите ее, вторая вернет результат, который будет выше первого), и что это займет очень долго, чтобы обмануть.
Правильно ли я понимаю, что причина, по которой вы это делаете, – скопировать другой код, чтобы вы могли измерить, сколько времени занимает другой код?
Я уверен, что вы знаете еще один хороший способ сделать это, просто закодируйте другой код 10 ^ 6 раз, запустите секундомер и вызовите его в микросекундах.
Как только вы измерили другой код, могу ли я предположить, что вы хотите знать, какие строки в нем стоит оптимизировать, чтобы сократить время?
Если это так, вы на хорошем уровне. Вы можете использовать инструмент, например Zoom или LTProf . Вот мой любимый метод.