|
1
Einleitung Doch wie vertrauenswürdig sind diese Messmittel? Ein nicht verstummendes Gerücht in der Internet-Hardwaregemeinde lautet, dass gewisse Prozessorbenchmarks die vergebenen Punktwertungen je nach Prozessorhersteller bewusst manipulieren. Erstmalig wurde dies 2008 von ArsTechnica mittels eines Via Nano-Systems beim Benchmark PCMark 2005 nachgewiesen [ArsTechnica]. Dieser Artikel stellt einen alternativen, softwarebasierten Ansatz vor, um unabhängig von exotischer Hardware Benchmarks überprüfen zu können. Hintergrund des Manipulationsverdachtes ist die mutmaßliche Existenz verschiedener Codepfade in einem Programm, welche unterschiedliche Befehlsfolgen enthalten, die zum gleichen Ergebnis führen. Dies ist legitim, sofern schnellere bzw. besser optimierte Codepfade auf spezielle Befehlssätze wie SSE oder AVX angewiesen sind und Prozessoren ohne diese Befehle einen langsameren Codepfad nutzen. Illegitim wäre es, wenn der optimierte Codepfad nur für CPUs eines Herstellers zugänglich wäre, also z.B. vom Vorhandensein einer bestimmten Herstellerbezeichnung abhängt. Die Gerüchteküche brodelt speziell um die Standardbenchmarks der Cinebench-Reihe, welche unter Mitwirkung eines Intel-Compilers entstanden sind. Für die Meinungsbildung im Internet sind dabei leider wissenschaftliche Grundsätze wie stichhaltige Beweisführung scheinbar recht belanglos, so dass sich anscheinend noch niemand die Mühe machte, der Sache auf den Grund zu gehen. Dieser Artikel soll diese Lücke anhand des Beispiels Cinebench R10 (32-Bit) schließen. Die dafür genutzte Methode eignet sich prinzipiell jedoch auch zur Überprüfung anderer Benchmarks. Cinebench R10 entstammt dem Jahr 2007, als noch Core 2 Duos und K8s die High-End-PCs befeuerten und erste Quad-Core Prozessoren erschienen. Es war damals ein in der Fachpresse häufig genutztes Messmittel, da es gut mit mehreren Kernen skaliert und die Mehrleistung der damals brandneuen Vierkern-Prozessoren mit vielen Punkten würdigte. Für die Untersuchung waren vier Software-Werkzeuge erforderlich:
Als Hardware-Plattform für die Überprüfung diente ein Sandy Brigde Doppelkern-Prozessor (Core-i7-2640M). Es ginge aber vermutlich auch jeder andere moderne Prozessor, sofern er von Intel stammt. Sollen Programme auf spezifische AMD oder Via-Optimierungen überprüft werden, benötigt man einen Prozessor von eben diesen Herstellern. 2 Identifikation verdächtigen Maschinencodes Die Datei „Cinebench R10.exe“ enthält x86 Maschinencode, welcher direkt auf dem Hauptprozessor ausgeführt wird. Sofern verdächtige Stellen darin auftauchen, haben diese mit dem x86 Maschinenbefehl „0FA2h“ (? das kleine h am Ende steht für die Kennzeichnung der Zeichenfolge davor als Hexadezimalzahl). Bekannter ist dessen Assembler-Repräsentation „cpuid“. Der Befehl samt Eingangsparameter und Ausgabewerten wird in [3] erklärt. Skizzenhaft beschrieben, betrachtet „cpuid“ das Prozessorregister eax, und befüllt, je nach in eax stehender Bitfolge, anschließend die Register eax, ebx, ecx und edx mit Informationen über den Prozessor. Das können Informationen über den Hersteller, zur Cache-Organisation oder zu unterstützten Befehlssätzen sein. Um verdächtige Stellen zu finden, öffnet man mit dem Borg Disassembler die exe-Datei unter Verwendung des Befehlssatzes „Pentium II with KNI“. Borg analysiert anschließend den Code und stellt ihn im Schema von Codebeispiel 1 dar. In der linken Spalte steht die hexadezimale Adresse („Stelle“) des Maschinencodes (mit dem Vorsatz „1000:“ und ohne h am Ende) in der exe-Datei. Dahinter der Maschinencode in Hexadezimalschreibweise (z.B. „55“, auch ohne h am Ende) und am Ende die Übersetzung in Assembler-Code (z.B. „push ebp“).
Codebeispiel 1: An der Stelle 00ba6339h des Programms wird „cpuid“ aufgerufen. Für den Eingangsparameter des cpuid-Befehls ist die Zeile davor mit dem Befehl „xor eax, eax“ wichtig. Dort wird bitweise die xor-Verknüpfung des Registers eax mit sich selbst vorgenommen. Bei xor ergeben 0 und 0 sowie 1 und 1 jeweils 0, 0 und 1 sowie 1 und 0 ergeben jeweils 1 [4]. Folglich ergibt die Verknüpfung einer Zahl mit sich selbst für alle Bits null, was im Zielregister eax hinterlegt wird. Der cpuid-Befehl in der nächsten Stelle 00ba6339h wird also mit dem Operanden 00000000h (hexadezimal) im Register eax ausgeführt und legt gemäß [cpuid] in den Registern ebx, ecx und edx den sogenannten „Vendor-ID-String“ ab, welcher den CPU-Hersteller identifiziert. 3 Manipulation des Maschinencodes Hinter der Stelle 00ba6339h folgen vier Zeilen, in welchen die cpuid-Werte per mov aus den Registern in den Arbeitsspeicher geschrieben werden. Zum Nachweis von herstellerspezifischer Codepfaden kann nun die betreffende Stelle im Maschinencode des Programms manipuliert werden. Hierzu werfen wir einen Blick auf die drei Stellen 00ba633eh, 00ba6341h und 00ba6344h in Codebeispiel 3, welche aus Codebeispiel 2 entstammen:
Codebeispiel 3: Der Inhalt des Registers ebx wird an die Stelle [ebp-08h] kopiert, ecx an die Stelle [epb-14h] und edx an die Stelle [ebp-10h]. ebp ist ein Pointer im Prozessor, aus welchen nach Subtraktion der nachfolgenden Hexadezimalzahl die Zieladresse im Arbeitsspeicher errechnet wird. Im Arbeitsspeicher hat man dann bei einem Intel-Prozessor den String „GenuineIntel“, bei einem AMD-Prozessor „AuthenticAMD“ und bei einem Via Prozessor „CentaurHauls“ stehen.
Abbildung 1: Der Maschinencode
in Cinebench R10.exe vor und nach der Modifikation Neben der in Codebeispiel 1 gezeigten Stelle finden sich weitere cpuid-Befehle in der deassemblierten "Cinebench R10.exe", welche teilweise mit anderen eax-Argumenten aufgerufen werden. Auch um diese wurde der Maschinencode verändert, es zeigten sich dabei jedoch nur bei den zwei in Codebeispiel 2 enthaltenen Stellen signifikante Änderungen am Benchmark Ergebnis. Dies bedeutet im Endeffekt, dass der Nachweis von herstellerspezifischen Optimierungen sprichwörtlich eine Suche der Nadel im Heuhaufen ist. 4 Messergebnisse Abschließend vergleicht man die Messergebnisse des Programms im Originalzustand mit jenen des Programms nach Modifikation von „Cinebench R10.exe“ und „advancedrenderer.cdl“. Hierfür standen die in Tab. 1 verwendeten Systeme zur Verfügung. Das Durchprobieren, ob einzelne cpuid-Aufrufe einen Einfluss auf den Punktwert haben, wurde ausschließlich auf dem Core-i7-2640M durchgeführt. Tabelle 1: Übersicht der zur Überprüfung des Mods verwendeten Systeme * - Turbo wurde deaktiviert Aus Gründen der Reproduzierbarkeit wurde nur der Single-Threaded Modus von Cinebench R10 genutzt, da eine andere Rechengeschwindigkeit in Teilen des Bildes die Programmentscheidung zum Start eines neuen Threads beeinflussen könnte. Jede Messung wurde zehnmal wiederholt um eine statistisch valide Schätzung der Messgenauigkeit zu erhalten. Tab. 2 enthält die Messergebnisse der einzelnen Prozessoren. Die
Punktwertänderung beim AMD K8 und der AMD K10 durch den Vendor-ID-Mod
liegen jeweils unterhalb der Messunsicherheit und ist somit nicht
nachweisbar. Weniger eindeutig ist der Einfluss des Vendor-ID-Mods beim
Pentium-III basierten Celeron 1300 MHz. Dieser wird etwas höher
bewertet, sofern er aus Programmsicht kein Intel-Prozessor ist, wobei
die Veränderung die Messunsicherheit kaum übersteigt. Signifikant (d.h.
deutlich größer als die Messunsicherheit) verschlechtert sich das
Punktergebnis hingegen bei allen anderen Intel-Prozessoren. Beim
Core-2-Quad, Intel Atom, Sandy Bridge und Pentium M sind es ca. um die
3 %, beim Pentium IV hingegen sogar über 4,5 %. Nichts destotrotz bedeutet dies, dass ein und derselbe Prozessor anders (i.d.R. schlechter) bewertet wird, wenn er aus Programmsicht nicht die Intel-Vendor-ID-Bezeichnung „GenuineIntel“ trägt. Dies legt den Schluss nah, dass besonders optimierte Codepfade nur von CPUs eines Herstellers genutzt werden dürfen, was zumindest den Verdacht der Manipulation aufkeimen lässt. Völlig unklar ist dabei jedoch, ob der Codepfad mutwillig eingebaut wurde oder vom wem er eingebaut wurde. Kein normaler Softwareentwicklern liest nach dem Kompilieren den von ihm erzeugten Maschinencode per Hand und überprüft ihn. Ebenso wissen wir nicht, ob eine AMD oder VIA CPU von der Nutzung eines alternativen Codepfads überhaupt profitieren oder sich wie der Pentium III verhalten würde. Auf quantitativer Sicht ist festzuhalten, dass der aufgedeckte Grad der Messwertverfälschung mit maximal 4,5 % und meist nur ca. 3 % recht gering ist. Bei Verwendung verschiedener Betriebssystemkonfigurationen und Hintergrundprogramme liegt er fast schon im Bereich der Messgenauigkeit. Da Cinebench R10 jedoch explizit als Messprogramm für Prozessoren erschien, sollten systematische, herstellerabhängige Messabweichungen möglichst komplett ausgeschlossen sein. Neben der Rechengeschwindigkeit ist auch die Frage relevant, ob beide Codepfade das gleiche Ergebnis, d.h. das gleiche Ausgabebild, produzieren. Diese Frage kann nicht beantwortet werden, da bereits die Ausgabe verschiedener Durchläuf mit einem Programmzustand voneinander abweicht. Um dies nachzuweisen, fertigt man eine Bildschirmkopie des Ausgabebildes auf, fügt es z.B. in GIMP ein und legt die Bildschirmkopie eines zweiten Durchlaufs darüber. Man erkennt dann, dass z.B. im Bereich direkt unter dem gerenderten Motorrad beide Bilder ein unterschiedliches Rauschen zeigen. Die Differenz zwischen beiden Codepfaden ist kleiner als dieses Rauschen und somit nicht nachweisbar. 5 Schlussfolgerungen und Quellen Generell eröffnen sich aus den Ergebnissen zwei grundlegende Fragen hinsichtlich der „Fairness“ von CPU-Benchmarks:
b) Welcher Grad von Transparenz ist für die Wahl der Codepfade bzw. des
genutzten Befehlssatzes (SSE, AVX, …) bei einer bestimmten CPU nötig? Insofern bleibt aus meiner Sicht nur der Test von fertigen Benchmarks hinsichtlich herstellerspezifischer Optimierungen. Der dargelegte Weg ist manuell durchgeführt zu aufwändig, so dass er automatisiert werden müsste. Weiterhin ist auch festzuhalten, dass böswillige Manipulationen sich damit nicht aufdecken lassen. Maschinencode kann z.B. erst zur Laufzeit entschlüsselt und dann ausgeführt werden. Im speziellen Fall von Cinebench R10 ist die Bewertung der Ergebnisse zudem hinsichtlich der Anwendungsrelevanz des Benchmarks komplizierter: Für Ersteller computeranimierter Filme sind die Stromkosten der Rendermaschinen ein wesentlicher Kostenfaktor. Zur Kostenminimierung wird dann natürlich der bestmögliche Kompiler eingesetzt, welcher von Intel stammt. Wenn sich dessen Kompilate immer so verhalten wie Cinebench R10, misst es für diesen speziellen Anwendungsfall Rendering richtig. Die meisten Anwendugsprogramme für Windows werden jedoch immer noch mit
Microsoft-Compilern erstellt. Somit ist die vom Cinebench Hersteller
Maxon propagierte Anwendungsrelevanz des Benchmarks doch überzogen
dargestellt [5]: Quellen: [1] - Via Nano Review Februar 2016 |