Как узнать частоту процессора c
Однако существует ли программный способ расчета частоты каждого ядра (и каждого процессора в многопроцессорных системах с несколькими ядрами на ЦП) без необходимости иметь дело с конкретной информацией ЦП.
Я пытаюсь разработать инструмент защиты от мошенничества (для использования с соревнованиями по тестированию с ограничением тактовой частоты), который сможет записывать тактовую частоту процессора во время выполнения теста для всех активных ядер в системе (для всех процессоров).
У меня пытался делать что-то подобное раньше - я автор одного из таких тестов оверклокера. Это очень жесткий. Вы не можете просто измерить частоту, вы также должны сделать системные таймеры устойчивыми к взлому часов . - Mysticial
Чтобы добавить к моей точке зрения. Методы измерения частоты включают аппаратные счетчики / счетчики производительности. Но вам нужно точное измерение продолжительности (например, количества циклов в 1 секунду). Однако, когда вы имеете дело с решительными мошенниками, вы не можете доверять результатам любой из этих функций: clock() , gettimeofday() , QueryPerformanceCounter() и т. д., поскольку все они могут быть изменены. (И я сам умею их трогать . ) - Mysticial
Вау . это показательно . вы наконец-то решили разработать стратегию, которая должна, по крайней мере, усложнить кому-то «легкое» мошенничество? - kidoman
Я подробно рассказал об этом в только что опубликованном ответе. - Mysticial
Вы пометили это конкретным семейством процессоров? - curiousguy
2 ответа
Он вообще не измеряет тактовую частоту, он измеряет, сколько итераций цикла может быть выполнено в секунду. Нет правила, согласно которому за такт будет выполняться одна итерация. Это может иметь место, и вы, возможно, действительно обнаружили, что это так - конечно, с оптимизированным кодом и разумным ЦП бесполезный цикл не должен работать намного медленнее, чем это. Однако он может работать на половинной скорости, некоторые процессоры не могут отключать более 1 взятой ветви каждые 2 цикла. А на эзотерические цели все ставки отключены.
Так что нет, это не измеряет тактовые циклы, кроме как случайно. В общем, очень сложно получить эмпирическую тактовую частоту (вы можете спросить свою ОС, какие, по ее мнению, максимальная тактовая частота и текущая тактовая частота, см. Ниже), потому что
Если вы измеряете, сколько времени занимает цикл, вы должны знать (хотя бы приблизительно) количество циклов на итерацию. Это достаточно серьезная проблема в сборке, требующая довольно подробных знаний ожидаемых микроархитектур (может быть, длинная цепочка зависимых инструкций, каждая из которых может занимать только 1 цикл, например add eax, 1 - достаточно длинная цепочка, которая различается в тесте / пропускная способность ветви становится достаточно маленькой, чтобы ее можно было игнорировать), поэтому очевидно, что все, что вы там делаете, непереносимо и будет иметь встроенные предположения, может стать ложным (на самом деле есть другой ответ на SO, который делает это и предполагает, что addps имеет латентность 3, чего больше нет на Skylake и не было на старых AMD). В C? Сдавайся сейчас же. Компилятор может запускать какой-нибудь генератор случайного кода, и полагаться на его разумность - все равно что делать то же самое с медведем. Угадывать количество циклов на итерацию кода, который вы не контролируете и даже не знаете , - просто глупость. Если это просто на вашем компьютере, вы можете проверить код, но тогда вы можете просто проверить тактовую частоту вручную, так что ..Can't load full resultsTry againRetrying. Retrying.
Если вы измеряете количество тактов, прошедших за заданное время настенных часов . но это сложно. Потому что rdtsc не измеряет тактовые циклы (больше нет), и ничто другое не приближается. Вы можете измерить что-то , но с масштабированием частоты и турбо, как правило, это не будет фактических тактовых циклов. Вы можете получить фактические тактовые циклы из счетчика производительности, но не можете сделать это в пользовательском режиме. Очевидно, что любой способ сделать это непереносим, потому что вы не можете переносимо запросить количество прошедших тактовых циклов.
Так что, если вы делаете это для получения актуальной информации, а не просто для того, чтобы возиться, вам, вероятно, следует просто спросить ОС. Для Windows запросите WMI для CurrentClockSpeed или MaxClockSpeed, в зависимости от того, что вы хотите. В Linux есть вещи в /proc/cpuinfo . По-прежнему не портативный, но тогда и решения нет.
как узнать, сколько ядер задействовано в процессе?
1. Конечно, ваш поток может перемещаться между ядрами, но поскольку у вас есть только один поток, он может быть только на одном ядре в любое время.
Хороший оптимизатор может удалить цикл, поскольку
Оказывает такое же влияние на состояние программы, как и;
Таким образом, оптимизатор может полностью освободить ваш цикл.
Таким образом, вы не можете измерить скорость процессора таким образом, поскольку она зависит от компилятора так же, как и от компьютера (не говоря уже о переменной тактовой частоте и уже упомянутой многоядерной архитектуре)
6 ответы
Я расширю свои комментарии здесь. Это слишком много и подробно для меня, чтобы поместиться в комментариях.
То, что вы пытаетесь сделать, очень сложно - до такой степени, что это непрактично по следующим причинам:
- Нет портативного способа узнать частоту процессора. rdtsc делает НЕ всегда задавайте правильную частоту благодаря таким эффектам, как SpeedStep и Turbo Boost.
- Все известные методы измерения частоты требуют точного измерения времени. Однако решительный читер может вмешаться во все часы и таймеры в системе.
- Точное считывание частоты процессора и времени с защитой от несанкционированного доступа потребует доступа на уровне ядра. Это подразумевает подпись драйвера для Windows.
Нет портативного способа узнать частоту процессора:
«Легкий» способ узнать частоту процессора - вызвать rdtsc дважды с фиксированной продолжительностью между ними. Тогда разделение разницы даст вам частоту.
Проблема в том, что rdtsc не дает истинную частоту процессора. Поскольку от него зависят приложения реального времени, например игры, rdtsc должен быть последовательным за счет регулирования ЦП и Turbo Boost. Итак, как только ваша система загрузится, rdtsc всегда будет работать с одинаковой скоростью (если только вы не начнете путаться со скоростью автобуса с SetFSB или что-то).
Например, на моем Core i7 2600K, rdtsc всегда будет показывать частоту на 3.4 GHz . Но на самом деле он простаивает на 1.6 GHz и часы до 4.6 GHz под нагрузкой через разогнанный множитель Turbo Boost на 46x .
Но как только вы найдете способ измерить истинную частоту (или вы будете достаточно довольны rdtsc ), вы можете легко получить частоту каждого ядра, используя сходство с нитями.
Получение истинной частоты:
Чтобы получить истинную частоту процессора, вам необходимо получить доступ либо к MSR (регистры для конкретной модели), либо к аппаратным счетчикам производительности.
Это инструкции уровня ядра, поэтому для них требуется драйвер. Если вы пытаетесь сделать это в Windows с целью распространения, вам, следовательно, потребуется пройти через соответствующий протокол подписи драйверов. Кроме того, код будет отличаться в зависимости от производителя и модели процессора, поэтому вам потребуются разные коды обнаружения для каждого поколения процессоров.
Как только вы дойдете до этого этапа, есть множество способов определить частоту.
На процессорах Intel аппаратные счетчики позволяют подсчитывать необработанные циклы ЦП. В сочетании с методом точного измерения в реальном времени (следующий раздел) вы можете вычислить истинную частоту. MSR дают вам доступ к другой информации, такой как множитель частоты процессора.
Все известные методы измерения частоты требуют точного измерения времени:
Возможно, это большая проблема. Чтобы измерить частоту, вам понадобится таймер. Способный хакер сможет подделать все часы, которые вы можете использовать в C / C ++. Это включает в себя все следующее:
- clock()
- gettimeofday()
- QueryPerformanceCounter()
- и т.д.
У этого списка нет конца. Другими словами, вы не можете доверять ни одному из таймеров, так как способный хакер сможет подделать их все. Например clock() и gettimeofday() можно обмануть, изменив системные часы прямо в ОС. Обман QueryPerformanceCounter() сложнее.
Получение истинного измерения времени:
Все перечисленные выше часы уязвимы, потому что они часто тем или иным образом основаны на одной и той же системной базовой частоте. И эти системные базовые часы часто привязаны к системным базовым часам, которые можно изменить после того, как система уже загрузилась, с помощью утилит разгона.
Таким образом, единственный способ получить надежное и защищенное от несанкционированного доступа измерение времени - это считывание показаний внешних часов, таких как ХПЭТ или ACPI. К сожалению, они также, похоже, требуют доступа на уровне ядра.
Подвести итоги:
Создание любого тестового теста с защитой от несанкционированного доступа почти наверняка потребует написания драйвера режима ядра, который требует подписи сертификата для Windows. Это часто становится слишком большим бременем для случайных авторов тестов.
Это привело к нехватке тестов с защитой от несанкционированного доступа, что, вероятно, способствовало общему упадку конкурентного сообщества оверклокеров в последние годы.
Я пытаюсь получить ТЕКУЩУЮ тактовую частоту процессора (не использование, базовое, мин. / Макс.). Я пробовал использовать ManagementObjects, но «CurrentClockSpeed» всегда дает фиксированное значение 3400 или 3,4 ГГц, что является максимальной стандартной скоростью процессора. Я пробовал много раз, и это дает мне тот же ответ, так что я думаю, это не просто совпадение.
Возможно, это наивный вопрос, но почему, помимо разгона, может измениться скорость процессора? «Скорость» - это сколько вычислений выполняется за время может, верно? Все остальное - это утилизация, которая вас не интересует.
Не беспокойтесь, все это немного запутанно! Я думаю, что, когда вы говорите о «скорости», вы могли бы подумать, это то, что мы могли бы назвать нашей максимальной тактовой частотой (которую производители предоставляют при покупке процессора). Эта скорость просто говорит нам о максимальной (если не разогнанной) скорости, на которой он должен работать, и о том, с какой скоростью вы должны ожидать, что он будет работать. Но я ищу текущую тактовую частоту. Это просто говорит нам значение в ГГц, на котором процессор обменивается данными. Ваша тактовая частота всегда повышается и понижается в зависимости от загрузки процессора, потому что не всегда нужно работать на 100%.
CurrentClockSpeed кажется правильным свойством. Мой варьируется от 2900 до 2901 на этом процессоре, который я сейчас использую. Вы уверены, что ваш показатель должен быть ниже?
Хммм, а у вас случайно есть код? Я очень уверен. Я запускал его в разных вариантах и основывал на диспетчере задач. Он просто возвращает базовое значение, несмотря ни на что, даже если текущая скорость намного ниже.
@Corak why would the speed of the CPU change? по ряду причин. Например, современные процессоры автоматически дросселируются при обнаружении перегрева в качестве средства защиты. ОС также может запросить работу процессора на пониженной тактовой частоте для экономии энергии.
Вы вообще не пробовали напрягать ЦП? Откройте несколько интенсивных программ и дайте им посидеть несколько минут, а затем попробуйте очистить + перестроить + запустить программу. Сообщите нам, если номер остался прежним.
Я использую совершенно другой код, и он мне подходит, но ваш тоже должен работать нормально. Может быть, ваш процессор всегда работает на максимальной мощности?
Не могли бы вы предоставить код? Хотелось бы посмотреть, как устроена ваша по сравнению с моей. Я проверял текущую тактовую частоту во время тестов, и в большинстве случаев она не работала близко к максимальной тактовой частоте.
@ user9622460 - Я думаю, вам нужно повторно создать экземпляр ManagementObject между чтениями. Попробуйте сделать следующее и посмотрите, получится ли у вас другие показания: for (int i = 0; i < 10; i++) < using (var mo = new ManagementObject("Win32_Processor.DeviceID='CPU0'")) < var sp = (uint)(mo["CurrentClockSpeed"]); Console.WriteLine(sp); >System.Threading.Thread.Sleep(1000); > - и да, позвольте процессору чем-нибудь заняться между чтениями.
@ user9622460 Просто тестирую с Создатель кода WMI.
@Corak, поэтому я попробовал этот метод и получил другой результат, но это только сбивает с толку. При этом я держал диспетчер задач, чтобы посмотреть, насколько он был близок, и, как обычно, он не был близок. Единственные изменения, которые он внес, - это 2400. Это очень странно и заставляет меня думать, что это все еще не работает. Если вы знаете процессоры, они довольно быстро меняются взад и вперед, и, как правило, они не округляются до заданного числа снова и снова. У любого, у кого это работает, есть код, который я могу проверить?
Выясните, что значение 2400 - это минимальное значение.
Так кто-нибудь нашел ответ на мою проблему? Я обнаружил проблему с настройкой значения часов, но все еще не уверен, почему оно неточно?
Я пытаюсь выяснить, есть ли в любом случае, чтобы получить представление о частоте процессора системы, в которой работает мой код C.
чтобы уточнить, я ищу абстрактное решение (которое не будет привязано к определенной архитектуре или ОС), которое может дать мне представление о рабочей частоте компьютера, на котором выполняется мой код. Мне не нужно быть точным, но я хотел бы быть в парке (т. е. У меня есть процессор 2.2 GHz, я хотел бы иметь возможность сказать в своей программе, что Я в пределах нескольких сотен МГц от этого)
есть ли у кого-нибудь идея использовать стандартный код C?
Как найти частоту процессора архитектуры и зависимые ОС, и нет абстрактных решений.
Если бы мы были 20+ лет назад, и вы использовали ОС без переключения контекста, и процессор выполнил инструкции, данные ему по порядку, вы могли бы написать некоторый код C в цикле и времени, а затем на основе сборки он был скомпилирован в вычислить количество инструкций во время выполнения. Это уже делает предположение, что каждая инструкция занимает 1 такт, который это довольно плохое предположение с тех пор, как конвейерные процессоры.
но любая современная ОС будет переключаться между несколькими процессами. Даже тогда, вы можете попытаться время кучу одинаковых for цикл выполняется (игнорируя время, необходимое для ошибок страницы и нескольких других причин, по которым ваш процессор может остановиться) и получить медианное значение.
и даже если предыдущее решение работает, у вас есть многоэтапные процессоры. С любым современным процессором это честная игра, чтобы переупорядочить ваши инструкции, выпускайте их в одном такте или даже разделяйте на ядра.
чтобы сделать это, вы сначала делаете то, что делаете 20 лет назад. Вы пишете некоторый код с циклом, где вы знаете задержку и время ее. Вот что я использовал:
это имеет зависимость от цикла переноса, поэтому процессор не может изменить порядок, чтобы уменьшить задержку. Это всегда занимает 3 часа циклы за итерацию. ОС не будет переносить поток в другое ядро, потому что мы свяжем потоки.
затем вы запускаете эту функцию на каждом физическом ядре. Я сделал это с OpenMP. Нити должны быть связаны для этого. В linux с GCC вы можете использовать export OMP_PROC_BIND=true чтобы связать потоки и предполагая, что у вас есть ncores физическое ядро также export OMP_NUM_THREADS=ncores . Если вы хотите программно связать и найти количество физических ядер для процессоров Intel, см. Это программно-определить число физических процессоров-ядер-или-если-многопоточность и thread-affinity-with-windows-msvc-and-openmp.
наконец запустите пробоотборник в цикле и распечатайте результаты
для полноты уже существует простое, быстрое, точное решение для пользовательского режима с огромным недостатком: оно работает только на процессорах Intel Skylake, Kabylake и более новых. Точное требование-поддержка уровня CPUID 16h. Согласно руководству разработчика программного обеспечения Intel 325462 release 59, страница 770:
Однако существует ли программный способ расчета частоты для каждого ядра (и для каждого процессора в многопроцессорных системах с несколькими ядрами на ЦП) без необходимости иметь дело с конкретной информацией о ЦП.
Я пытаюсь разработать инструмент для защиты от мошенничества (для использования с соревнованиями по тестированию с ограничением тактовой частоты), который сможет записывать тактовую частоту процессора во время выполнения теста для всех активных ядер в системе (для всех процессоров).
Я расширю свои комментарии здесь. Это слишком много и подробно для меня, чтобы поместиться в комментариях.
То, что вы пытаетесь сделать, очень сложно - до такой степени, что это непрактично по следующим причинам:
- Нет портативного способа узнать частоту процессора. rdtsc не всегда NOT выдает правильную частоту из-за таких эффектов, как SpeedStep и Turbo Boost.
- Все известные методы измерения частоты требуют точного измерения времени. Однако решительный читер может вмешаться во все часы и таймеры в системе.
- Точное считывание частоты процессора и времени с защитой от несанкционированного доступа потребует доступа на уровне ядра. Это подразумевает подпись драйвера для Windows.
Нет портативного способа узнать частоту процессора:
"Легкий" способ узнать частоту ЦП - это дважды вызвать rdtsc с фиксированная продолжительность между ними. Тогда разделение разницы даст вам частоту.
Проблема в том, что rdtsc не дает истинной частоты процессора. Поскольку от него зависят приложения реального времени, такие как игры, rdtsc должен быть согласован за счет дросселирования ЦП и Turbo Boost. Поэтому после загрузки системы rdtsc всегда будет работать с той же скоростью (если только вы не начнете изменять скорость шины с помощью SetFSB или что-то в этом роде).
Например, на моем Core i7 2600K rdtsc всегда будет показывать частоту на 3.4 GHz . Но на самом деле он простаивает на 1.6 GHz и разгоняется до 4.6 GHz под нагрузкой за счет разогнанного множителя Turbo Boost на 46x .
Но как только вы найдете способ измерить истинную частоту (или вы будете достаточно довольны rdtsc ), вы можете легко получить частоту каждого ядра, используя сходство потоков.
Получение истинной частоты:
Чтобы получить истинную частоту процессора, вам необходимо получить доступ либо к MSR (регистры для конкретной модели), либо к аппаратным счетчикам производительности.
Это инструкции уровня ядра, поэтому для них требуется драйвер. Если вы пытаетесь сделать это в Windows с целью распространения, вам, следовательно, потребуется пройти через соответствующий протокол подписи драйверов. Кроме того, код будет отличаться в зависимости от производителя и модели процессора, поэтому вам потребуются разные коды обнаружения для каждого поколения процессоров.
Как только вы дойдете до этого этапа, есть множество способов определить частоту.
На процессорах Intel аппаратные счетчики позволяют подсчитывать необработанные циклы ЦП. В сочетании с методом точного измерения в реальном времени (следующий раздел) вы можете вычислить истинную частоту. MSR дают вам доступ к другой информации, такой как множитель частоты процессора.
Все известные методы измерения частоты требуют точного измерения времени:
Возможно, это большая проблема. Чтобы измерить частоту, вам понадобится таймер. Способный хакер сможет подделать все часы, которые вы можете использовать в C / C ++. Это включает в себя все следующее:
- clock()
- gettimeofday()
- QueryPerformanceCounter()
- Др.
У этого списка нет конца. Другими словами, вы не можете доверять ни одному из таймеров, так как способный хакер сможет подделать их все. Например, clock() и gettimeofday() можно обмануть, изменив системные часы непосредственно в ОС. Обмануть QueryPerformanceCounter() сложнее.
Получение точного измерения времени:
Все перечисленные выше часы уязвимы, потому что они часто тем или иным образом основаны на одной и той же системной базовой частоте. И эти системные базовые часы часто привязаны к системным базовым часам, которые можно изменить после того, как система уже загрузилась, с помощью утилит разгона.
Таким образом, единственный способ получить надежное и защищенное от несанкционированного доступа измерение времени - это считывание внешних часов, таких как HPET или ACPI. К сожалению, они также, похоже, требуют доступа на уровне ядра.
Подведем итоги:
Создание любого тестового теста с защитой от несанкционированного доступа почти наверняка потребует написания драйвера режима ядра, который требует подписи сертификата для Windows. Это часто становится слишком большим бременем для случайных авторов тестов.
Это привело к нехватке тестов с защитой от несанкционированного доступа, что, вероятно, способствовало общему упадку конкурентного сообщества оверклокеров в последние годы.
Следует обратиться к этому техническому документу: noreferrer "noreferrer". Технология Intel® Turbo Boost в процессорах на базе микроархитектуры Intel® Core ™ (Nehalem). Обычно производят несколько чтений фиксированного счетчика производительности UCC за период выборки T.
Начиная с архитектуры Nehalem, UCC увеличивает и уменьшает количество щелчков по сравнению с состоянием ядра Unhalted.
Когда активированы SpeedStep или Turbo Boost, расчетная частота с использованием UCC будет соответственно измерена; в то время как TSC остается постоянным. Например, Turbo Boost в действии показывает, что Delta (UCC) больше или равна Delta (TSC)
Пример функции Core_Cycle в функции Cyring | CoreFreq GitHub.
Вам необходимо использовать CallNtPowerInformation . Вот образец кода с сайта putil. С его помощью вы можете получить текущую и максимальную частоту процессора. Насколько я знаю, получить частоту процессора невозможно.
Алгоритм выполняет множество циклов для этого, что приводит к увеличению частоты процессора до максимума (как и во время тестов), поэтому программное обеспечение для регулирования скорости не вступает в игру.
Дополнительная информация здесь и здесь.
Что касается вопроса о регулировании скорости, я действительно не вижу в этом проблемы, если приложение не использует значения скорости для определения прошедшего времени, а сами времена чрезвычайно важны. Например, если для завершения деления требуется x тактовых циклов, не имеет значения, работает ли ЦП на частоте 3 ГГц или 300 МГц: ему все равно потребуется x тактовых циклов, и единственная разница в том, что он завершит деление за одну десятую. времени на @ 3 ГГц.
Один из самых простых способов сделать это - использовать RDTSC , но, поскольку он предназначен для механизмов защиты от мошенничества, я бы добавил его как драйвер ядра или резидентный фрагмент кода гипервизора.
Вероятно, вам также потребуется применить свой собственный код синхронизации **, что снова можно сделать с помощью RDTSC (QPC, используемый в приведенном ниже примере, использует RDTSC , и на самом деле его очень просто перепроектировать и используйте локальную копию, что означает, что для вмешательства в нее вам нужно будет вмешаться в свой драйвер).
** Я бы это сделал для безопасности, как упоминал @Mystical, но, поскольку я никогда не чувствовал побуждения ниспровергать механизмы синхронизации системы низкого уровня, это могло бы быть более задействовано, было бы неплохо, если бы Mystical мог что-то добавить к этому :)
Я понимаю, что на это уже был дан ответ. Я также понимаю, что это в основном черное искусство, поэтому, пожалуйста, примите его или оставьте - или поделитесь своим мнением.
В стремлении найти тактовую частоту на дросселированных (спасибо microsft, hp и dell) хостах HyperV (ненадежный счетчик производительности) и гостевых системах HyperV (можно получить только стандартную скорость процессора, а не текущую), мне удалось с помощью пробной ошибки и fluke, чтобы создать цикл, который повторяется ровно один раз за такт.
Я пытаюсь измерить скорость процессора, но не уверен, насколько точен мой метод. По сути, я пробовал пустой цикл for со значениями вроде UINT_MAX , но программа быстро завершалась, поэтому я попробовал UINT_MAX * 3 и так далее .
Затем я понял, что компилятор оптимизирует цикл, поэтому я добавил переменную volatile , чтобы предотвратить оптимизацию. Следующая программа длится примерно 1,5 секунды. Я хочу знать, насколько точен этот алгоритм измерения тактовой частоты. Кроме того, как мне узнать, сколько ядер задействовано в процессе?
Читайте также: