Ermitteln der CPU-Taktfrequenz (pro Kern, pro Prozessor)

Lesezeit: 11 Minuten

Programme wie CPUz sind sehr gut darin, detaillierte Informationen über das System (Busgeschwindigkeit, Speichertimings usw.)

Gibt es jedoch eine programmgesteuerte Möglichkeit, die Frequenz pro Kern (und pro Prozessor in Mehrprozessorsystemen mit mehreren Kernen pro CPU) zu berechnen, ohne sich mit CPU-spezifischen Informationen befassen zu müssen.

Ich versuche, ein Anti-Cheating-Tool zu entwickeln (zur Verwendung bei taktbegrenzten Benchmark-Wettbewerben), das in der Lage sein wird, den CPU-Takt während des Benchmark-Laufs für alle aktiven Kerne im System (über alle Prozessoren hinweg) aufzuzeichnen.

  • Ich habe versucht sowas schon mal gemacht zu haben – da ich Autor eines solchen Overclocker-Benchmarks bin. Es ist sehr schwer. Sie können nicht nur die Frequenz messen, Sie müssen auch die Systemtimer gegen Manipulationen der Uhr resistent machen …

    – Mystisch

    2. Dezember 11 um 4:56 Uhr


  • Um meinen Punkt zu ergänzen. Methoden zur Frequenzmessung beinhalten Hardware-/Leistungszähler. Sie benötigen jedoch eine genaue Messung einer Zeitdauer (z. B. die Anzahl der Zyklen in 1 Sekunde). Wenn Sie es jedoch mit einem entschlossenen Betrüger zu tun haben, können Sie den Ergebnissen dieser Funktionen nicht vertrauen: clock(), gettimeofday(), QueryPerformanceCounter(), etc… da sie alle manipuliert werden können. (Und ich weiß, wie man sie selbst manipuliert …)

    – Mystisch

    2. Dezember 11 um 5:03 Uhr


  • Wow … das ist aufschlussreich … hast du dich endlich für eine Strategie entschieden, um es jemandem zumindest schwer zu machen, “einfach” zu schummeln?

    – Kidomann

    2. Dezember 11 um 6:49 Uhr

  • Ich habe dies in der Antwort, die ich gerade gepostet habe, erweitert.

    – Mystisch

    2. Dezember 11 um 7:36 Uhr

  • Sie haben dies mit einer bestimmten CPU-Familie gekennzeichnet?

    – Neugieriger

    2. Dezember 11 um 14:06 Uhr

Ermitteln der CPU Taktfrequenz pro Kern pro Prozessor
Mystisch

Ich werde meine Kommentare hier erweitern. Das ist mir zu umfangreich und zu tiefgründig, um in die Kommentare zu passen.

Was Sie versuchen, ist sehr schwierig – bis hin zur Unpraktikabilität aus den folgenden Gründen:

  • Es gibt keine tragbare Möglichkeit, die Prozessorfrequenz zu ermitteln. rdtsc tut NICHT Geben Sie aufgrund von Effekten wie SpeedStep und Turbo Boost immer die richtige Frequenz an.
  • Alle bekannten Verfahren zur Frequenzmessung erfordern eine genaue Zeitmessung. Ein entschlossener Betrüger kann jedoch alle Uhren und Timer im System manipulieren.
  • Das genaue Lesen sowohl der Prozessorfrequenz als auch der Zeit auf manipulationssichere Weise erfordert Zugriff auf Kernel-Ebene. Dies impliziert die Treibersignierung für Windows.

Es gibt keine tragbare Möglichkeit, die Prozessorfrequenz zu ermitteln:

Der “einfache” Weg, um die CPU-Frequenz zu erhalten, ist ein Anruf rdtsc zweimal mit einer festen Zeitdauer dazwischen. Wenn Sie dann die Differenz teilen, erhalten Sie die Häufigkeit.

Das Problem ist, dass rdtsc gibt nicht die wahre Frequenz des Prozessors an. Da Echtzeitanwendungen wie Spiele darauf angewiesen sind, rdtsc muss durch CPU-Throttling und Turbo Boost konsistent sein. Sobald Ihr System hochgefahren ist, rdtsc wird immer mit der gleichen Geschwindigkeit laufen (es sei denn, Sie fangen an, mit den Busgeschwindigkeiten herumzuspielen SetFSB oder so).

Zum Beispiel auf meinem Core i7 2600K, rdtsc zeigt immer die Frequenz an 3.4 GHz. Aber in Wirklichkeit läuft es im Leerlauf 1.6 GHz und Uhren bis zu 4.6 GHz unter Last über den übertakteten Turbo-Boost-Multiplikator an 46x.

Aber sobald Sie einen Weg gefunden haben, die wahre Frequenz zu messen (oder Sie damit zufrieden sind rdtsc), können Sie die Frequenz jedes Kerns einfach abrufen, indem Sie verwenden Thread-Affinitäten.

Erhalten der wahren Frequenz:

Um die wahre Frequenz des Prozessors zu erhalten, müssen Sie entweder auf die MSRs (modellspezifische Register) oder die Hardwareleistungszähler zugreifen.

Dies sind Anweisungen auf Kernelebene und erfordern daher die Verwendung eines Treibers. Wenn Sie dies in Windows zum Zwecke der Verteilung versuchen, müssen Sie daher das richtige Treiber-Signaturprotokoll durchlaufen. Darüber hinaus unterscheidet sich der Code je nach Prozessormarke und -modell, sodass Sie für jede Prozessorgeneration einen anderen Erkennungscode benötigen.

Sobald Sie dieses Stadium erreicht haben, gibt es eine Vielzahl von Möglichkeiten, die Frequenz abzulesen.

Auf Intel-Prozessoren können Sie mit den Hardwarezählern rohe CPU-Zyklen zählen. In Kombination mit einer Methode zur präzisen Messung der Echtzeit (nächster Abschnitt) können Sie die wahre Frequenz berechnen. Die MSRs geben Ihnen Zugriff auf andere Informationen wie den CPU-Frequenzmultiplikator.


Alle bekannten Methoden zur Frequenzmessung erfordern eine genaue Zeitmessung:

Das ist vielleicht das größere Problem. Sie benötigen einen Timer, um die Frequenz messen zu können. Ein fähiger Hacker kann alle Uhren manipulieren, die Sie in C/C++ verwenden können. Dies beinhaltet alles Folgende:

  • clock()
  • gettimeofday()
  • QueryPerformanceCounter()
  • etc…

Die Liste geht weiter und weiter. Mit anderen Worten, Sie können keinem der Timer vertrauen, da ein fähiger Hacker in der Lage sein wird, sie alle zu manipulieren. Beispielsweise clock() und gettimeofday() kann getäuscht werden, indem die Systemuhr direkt im Betriebssystem geändert wird. Narren QueryPerformanceCounter() ist schwieriger.

Eine echte Zeitmessung erhalten:

Alle oben aufgeführten Uhren sind anfällig, da sie oft auf die eine oder andere Weise von der gleichen Systembasisuhr abgeleitet sind. Und dieser System-Basistakt ist oft an den System-Basistakt gebunden, der geändert werden kann, nachdem das System bereits mit Hilfe von Übertaktungsdienstprogrammen hochgefahren ist.

Die einzige Möglichkeit, eine zuverlässige und manipulationssichere Zeitmessung zu erhalten, besteht also darin, externe Uhren wie die auszulesen HPET oder der ACPI. Leider scheinen diese auch Zugriff auf Kernel-Ebene zu erfordern.


Zusammenfassen:

Das Erstellen eines beliebigen manipulationssicheren Benchmarks erfordert mit ziemlicher Sicherheit das Schreiben eines Kernelmodustreibers, der eine Zertifikatsignatur für Windows erfordert. Dies ist für gelegentliche Benchmark-Autoren oft eine zu große Belastung.

Dies hat zu einem Mangel an manipulationssicheren Benchmarks geführt, was wahrscheinlich zum allgemeinen Niedergang der konkurrierenden Overclocking-Community in den letzten Jahren beigetragen hat.

  • Kann man das per E-Mail besprechen? Ich wünschte, es gäbe hier auf SO eine Funktion für private Nachrichten.

    – Kidomann

    2. Dezember 11 um 8:59 Uhr

  • Da ich sowieso keine Details zu den Timer-Hacks preisgeben kann, könnten wir hier oder im Chat darüber sprechen. Es sei denn, Sie möchten etwas anderes besprechen, das privat sein muss.

    – Mystisch

    2. Dezember 11 um 9:06 Uhr

  • Wir haben kürzlich einen OC-Wettbewerb abgeschlossen und hatten einen fairen Anteil an verdächtigen Einsendungen. Ich wollte Ihnen ein paar Ideen zu den Gegenmaßnahmen mitteilen, die ich vorhabe, um zumindest den Richtern zu helfen, die Cheats besser zu erkennen. Ich bin bei karan AT erodov DOT com. Bitte schreiben Sie mir eine E-Mail, wenn wir diese Diskussionslinie weiterführen können 🙂

    – Kidomann

    2. Dezember 11 um 17:42 Uhr


  • Ich akzeptiere dies als Antwort, da dies meine Erwartungen richtig gemacht hat. Ich wünschte, Frank würde sein CPU-z SDK nicht so teuer bezahlen. Oder eine preisgünstigere Version für solche Verwendungen bereitgestellt. 1000+ Euro sind mir für einen kostenlosen Benchmark einfach zu viel.

    – Kidomann

    2. Dezember 11 um 17:47 Uhr

  • Hier ist ein guter Thread über Cheat-Benchmarks: (xtremesystems.org/forums/…) Sie finden meine E-Mail-Adresse über einen der Links in meinem Profil.

    – Mystisch

    2. Dezember 11 um 18:26 Uhr

Ermitteln der CPU Taktfrequenz pro Kern pro Prozessor
Patrick

Mir ist bewusst, dass dies bereits beantwortet wurde. Mir ist auch klar, dass dies im Grunde eine schwarze Kunst ist, also nehmen Sie es bitte oder lassen Sie es – oder geben Sie Feedback.

Bei der Suche nach der Taktrate auf gedrosselten (dank Microsft, HP und Dell) HyperV-Hosts (unzuverlässiger Leistungszähler) und HyperV-Gästen (können nur Standard-CPU-Geschwindigkeit abrufen, nicht aktuell), habe ich es durch Versuchsfehler und geschafft Fluke, um eine Schleife zu erstellen, die genau einmal pro Takt wiederholt wird.

Code wie folgt: C# 5.0, SharpDev, 32 Bit, Target 3.5, Optimize on (entscheidend), kein Debugger aktiv (entscheidend)

        long frequency, start, stop;
        double multiplier = 1000 * 1000 * 1000;//nano
        if (Win32.QueryPerformanceFrequency(out frequency) == false)
            throw new Win32Exception();

        Process.GetCurrentProcess().ProcessorAffinity = new IntPtr(1);
        const int gigahertz= 1000*1000*1000;
        const int known_instructions_per_loop = 1; 

        int iterations = int.MaxValue;
        int g = 0;

        Win32.QueryPerformanceCounter(out start);
        for( i = 0; i < iterations; i++)
        {
            g++;
            g++;
            g++;
            g++;
        }
        Win32.QueryPerformanceCounter(out stop);

        //normal ticks differs from the WMI data, i.e 3125, when WMI 3201, and CPUZ 3199
        var normal_ticks_per_second = frequency * 1000;
        var ticks = (double)(stop - start);
        var time = (ticks * multiplier) /frequency;
        var loops_per_sec = iterations / (time/multiplier);
        var instructions_per_loop = normal_ticks_per_second  / loops_per_sec;

        var ratio = (instructions_per_loop / known_instructions_per_loop);
        var actual_freq = normal_ticks_per_second / ratio;

        Console.WriteLine( String.Format("Perf counhter freq: {0:n}", normal_ticks_per_second));
        Console.WriteLine( String.Format("Loops per sec:      {0:n}", loops_per_sec));
        Console.WriteLine( String.Format("Perf counter freq div loops per sec: {0:n}", instructions_per_loop));
        Console.WriteLine( String.Format("Presumed freq: {0:n}", actual_freq));
        Console.WriteLine( String.Format("ratio: {0:n}", ratio));

Anmerkungen

  • 25 Anweisungen pro Schleife, wenn der Debugger aktiv ist
  • Erwägen Sie, vorher eine 2- oder 3-Sekunden-Schleife auszuführen, um den Prozessor hochzufahren (oder zumindest zu versuchen, hochzufahren, da Sie wissen, wie stark Server heutzutage gedrosselt werden).
  • Getestet auf einem 64bit Core2 und Haswell Pentium und verglichen mit CPU-Z

  • Oh sieht so aus, als hätte 7 Zip eine ähnliche Funktion. Hier ist ein Lauf, der auf einem „ausgeglichenen“ 2-GHz-2012-Server > 7z b -mmt = 1 7-Zip 9.38 Beta durchgeführt wurde 1396 RAM-Größe: 4095 MB, # CPU-Hardware-Threads: 12 RAM-Nutzung: 419 MB, # Benchmark-Threads: 1

    – Patrick

    10. August 15 um 6:13 Uhr


  • Nehalem und Westmere – CPU-Modell 26 und 44 – erfordern known_instructions_per_loop = 2

    – Patrick

    7. Oktober 15 um 1:33 Uhr

1642857013 536 Ermitteln der CPU Taktfrequenz pro Kern pro Prozessor
Nekrolis

Eine der einfachsten Möglichkeiten, dies zu tun, ist die Verwendung RDTSC, aber da dies für Anti-Cheating-Mechanismen ist, würde ich dies als Kernel-Treiber oder als Hyper-Visor-residenten Code einfügen.

Sie müssten wahrscheinlich auch Ihren eigenen Timing-Code ** rollen, was wiederum möglich ist RDTSC (QPC, wie es im Beispiel unten verwendet wird, verwendet RDTSC, und es ist in der Tat sehr einfach, eine lokale Kopie davon zurückzuentwickeln und zu verwenden, was bedeutet, dass Sie Ihren Treiber manipulieren müssten, um sie zu manipulieren).

void GetProcessorSpeed()
{
    CPUInfo* pInfo = this;
    LARGE_INTEGER qwWait, qwStart, qwCurrent;
    QueryPerformanceCounter(&qwStart);
    QueryPerformanceFrequency(&qwWait);
    qwWait.QuadPart >>= 5;
    unsigned __int64 Start = __rdtsc();
    do
    {
        QueryPerformanceCounter(&qwCurrent);
    }while(qwCurrent.QuadPart - qwStart.QuadPart < qwWait.QuadPart);
    pInfo->dCPUSpeedMHz = ((__rdtsc() - Start) << 5) / 1000000.0;
}

** Ich würde dies aus Sicherheitsgründen tun, wie @Mystical erwähnt hat, aber da ich nie den Drang verspürt habe, System-Timing-Mechanismen auf niedriger Ebene zu untergraben, könnte mehr involviert sein, wäre schön, wenn Mystical etwas dazu hinzufügen könnte 🙂

  • @BenVoigt: Ja, das wurde gepostet, lange bevor alle begannen, auf HPET-basiertes Timing umzusteigen, aber IIRC I kodiere diesen Code aus einem alten AMD-Beispiel für Mehrkernprozessoren … Was diesen Beitrag betrifft, sollten Sie die schreckliche Inline-Assembly entfernen und benutze die __rtdsc intrinsisch 😛

    – Nekrolis

    24. April 14 um 7:55 Uhr


  • QueryPerformanceCounter() war lange Zeit HPET-basiert auf dem Multiprozessor-Kernel, da TSC nicht über Prozessoren oder Kerne hinweg synchronisiert wird. Aber das Hauptproblem, auf das ich mich in Ihrem Code bezog, ist (1) das Beschäftigt-Warten (2), das nicht die tatsächlich verstrichene Zeit verwendet.

    – Ben Voigt

    24. April 14 um 14:10 Uhr

1642857014 634 Ermitteln der CPU Taktfrequenz pro Kern pro Prozessor
Olof Forshell

Ich habe bereits zu diesem Thema gepostet (zusammen mit einem grundlegenden Algorithmus): hier. Meines Wissens ist der Algorithmus (siehe Diskussion) sehr genau. Zum Beispiel meldet Windows 7 meinen CPU-Takt als 2,00 GHz, CPU-Z als 1994-1996 MHz und meinen Algorithmus als 1995025-1995075 kHz.

Der Algorithmus führt dazu viele Schleifen aus, was dazu führt, dass die CPU-Frequenz auf das Maximum ansteigt (wie auch während Benchmarks), sodass keine geschwindigkeitsdrosselnde Software ins Spiel kommt.

Weitere Infos hier und hier.

Zur Frage der Geschwindigkeitsdrosselung sehe ich es wirklich nicht als Problem an, es sei denn, eine Anwendung verwendet die Geschwindigkeitswerte, um die verstrichene Zeit zu bestimmen, und die Zeiten selbst sind extrem wichtig. Wenn beispielsweise eine Division x Taktzyklen benötigt, um abgeschlossen zu werden, spielt es keine Rolle, ob die CPU mit 3 GHz oder 300 MHz läuft: Sie benötigt immer noch x Taktzyklen und der einzige Unterschied besteht darin, dass sie die Division in einem Zehntel abschließt der Zeit bei @ 3 GHz.

Sie müssen verwenden CallNtPowerInformation. Hier ist ein Codebeispiel von putil Projekt. Damit können Sie die aktuelle und maximale CPU-Frequenz abrufen. Soweit ich weiß, ist es nicht möglich, die Frequenz pro CPU zu erhalten.

  • Dies könnte eine gute, praktische Antwort für Windows-Systeme sein. Leider gibt es keinen Code, der ein Beispiel für das gibt, was Sie vorschlagen. Die Suche auf der zitierten MSDN-Seite nach „Häufigkeit“ ergibt 0 Treffer. So wie es aussieht, sollte es wahrscheinlich ein Kommentar sein.

    – jww

    25. Dezember 17 um 20:24 Uhr


  • Unter Windows gibt es eine Struktur, die die aktuelle Frequenz (CurrentMhz-Mitglied) enthält – docs.microsoft.com/bg-bg/windows/win32/power/…

    – Das Gespenst

    19. März 20 um 17:09 Uhr


1642857014 339 Ermitteln der CPU Taktfrequenz pro Kern pro Prozessor
jww

Man sollte sich auf dieses Whitepaper beziehen: Intel® Turbo-Boost-Technologie in Intel® Core™-Mikroarchitektur (Nehalem)-basierten Prozessoren. Produzieren Sie grundsätzlich mehrere Lesevorgänge des festen UCC-Leistungszählers über einen Abtastzeitraum T.

Relative.Freq = Delta(UCC)  / T

Where:
   Delta() = UCC @ period T
                 - UCC @ period T-1

Beginnend mit der Nehalem-Architektur erhöht und verringert UCC die Anzahl der Klick-Ticks relativ zum Zustand „Unhalted“ des Kerns.

Wenn SpeedStep oder Turbo Boost aktiviert sind, wird die geschätzte Frequenz mit UCC entsprechend gemessen; während TSC konstant bleibt. Zum Beispiel zeigt Turbo Boost in Aktion, dass Delta (UCC) größer oder gleich Delta (TSC) ist.

Beispiel in Funktion Core_Cycle Funktion bei Cyring | Kernfreq GitHub.

  • Dies könnte eine gute, praktische Antwort für Windows-Systeme sein. Leider gibt es keinen Code, der ein Beispiel für das gibt, was Sie vorschlagen. Die Suche auf der zitierten MSDN-Seite nach „Häufigkeit“ ergibt 0 Treffer. So wie es aussieht, sollte es wahrscheinlich ein Kommentar sein.

    – jww

    25. Dezember 17 um 20:24 Uhr


  • Unter Windows gibt es eine Struktur, die die aktuelle Frequenz (CurrentMhz-Mitglied) enthält – docs.microsoft.com/bg-bg/windows/win32/power/…

    – Das Gespenst

    19. März 20 um 17:09 Uhr


.

590310cookie-checkErmitteln der CPU-Taktfrequenz (pro Kern, pro Prozessor)

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy