2016-05-17 14 views
6

Inspired by SQLite, Ich bin mit der Verwendung von Valgrind "Cachegrind" -Tool, um reproduzierbare Performance-Benchmarking zu tun. Die Zahlen, die es ausgibt, sind viel stabiler als jede andere Methode des Timings, die ich gefunden habe, aber sie sind immer noch nicht deterministisch. Als Beispiel ist hier ein einfaches C-Programm:Warum ist der Cache-Grind nicht vollständig deterministisch?

int main() { 
    volatile int x; 
    while (x < 1000000) { 
    x++; 
    } 
} 

Wenn ich es kompilieren und unter cachegrind laufen, erhalte ich folgende Ergebnisse:

$ gcc -O2 x.c -o x 
$ valgrind --tool=cachegrind ./x 
==11949== Cachegrind, a cache and branch-prediction profiler 
==11949== Copyright (C) 2002-2015, and GNU GPL'd, by Nicholas Nethercote et al. 
==11949== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info 
==11949== Command: ./x 
==11949== 
--11949-- warning: L3 cache found, using its data for the LL simulation. 
==11949== 
==11949== I refs:  11,158,333 
==11949== I1 misses:   3,565 
==11949== LLi misses:   2,611 
==11949== I1 miss rate:  0.03% 
==11949== LLi miss rate:  0.02% 
==11949== 
==11949== D refs:  4,116,700 (3,552,970 rd + 563,730 wr) 
==11949== D1 misses:  21,119 ( 19,041 rd + 2,078 wr) 
==11949== LLd misses:   7,487 ( 6,148 rd + 1,339 wr) 
==11949== D1 miss rate:  0.5% (  0.5%  +  0.4% ) 
==11949== LLd miss rate:  0.2% (  0.2%  +  0.2% ) 
==11949== 
==11949== LL refs:   24,684 ( 22,606 rd + 2,078 wr) 
==11949== LL misses:   10,098 ( 8,759 rd + 1,339 wr) 
==11949== LL miss rate:   0.1% (  0.1%  +  0.2% ) 
$ valgrind --tool=cachegrind ./x 
==11982== Cachegrind, a cache and branch-prediction profiler 
==11982== Copyright (C) 2002-2015, and GNU GPL'd, by Nicholas Nethercote et al. 
==11982== Using Valgrind-3.11.0.SVN and LibVEX; rerun with -h for copyright info 
==11982== Command: ./x 
==11982== 
--11982-- warning: L3 cache found, using its data for the LL simulation. 
==11982== 
==11982== I refs:  11,159,225 
==11982== I1 misses:   3,611 
==11982== LLi misses:   2,611 
==11982== I1 miss rate:  0.03% 
==11982== LLi miss rate:  0.02% 
==11982== 
==11982== D refs:  4,117,029 (3,553,176 rd + 563,853 wr) 
==11982== D1 misses:  21,174 ( 19,090 rd + 2,084 wr) 
==11982== LLd misses:   7,496 ( 6,154 rd + 1,342 wr) 
==11982== D1 miss rate:  0.5% (  0.5%  +  0.4% ) 
==11982== LLd miss rate:  0.2% (  0.2%  +  0.2% ) 
==11982== 
==11982== LL refs:   24,785 ( 22,701 rd + 2,084 wr) 
==11982== LL misses:   10,107 ( 8,765 rd + 1,342 wr) 
==11982== LL miss rate:   0.1% (  0.1%  +  0.2% ) 
$ 

In diesem Fall unterscheidet sich "I Refs" von nur 0,008% zwischen den beiden Läufen, aber ich frage mich immer noch, warum diese anders sind. In komplexeren Programmen (mehrere zehn Millisekunden) können sie um mehr variieren. Gibt es eine Möglichkeit, die Läufe vollständig reproduzierbar zu machen?

+0

eine weniger anspruchsvolle CPU verwenden, die nicht zum Beispiel Verzweigungsvorhersage zu tun. –

+1

Wenn ich richtig verstehe, simuliert Valgrind seine eigene CPU und führt keine Verzweigungsvorhersage durch, wenn Sie nicht --branch-sim = yes übergeben. Warum kann die Verzweigungsvorhersage bei der Simulation einer CPU nicht deterministisch sein? –

Antwort

5

Am Ende a topic in gmane.comp.debugging.valgrind, Nicholas Nethercote (ein Mozilla-Entwickler im Team Valgrind Entwickler arbeiten) sagt, dass geringfügige Änderungen üblich sind Cachegrind mit (und ich kann daraus schließen, dass sie nicht zu großen Problemen führen).

Cachegrind’s manual erwähnt, dass das Programm sehr empfindlich ist. Zum Beispiel kann unter Linux die Adressraum-Randomisierung (die zur Verbesserung der Sicherheit verwendet wird) die Quelle der Nicht-Deterministik sein.

Eine andere Sache ist bemerkenswert, dass die Ergebnisse sehr empfindlich sind. die Größe der ausführbaren Ändern Profil erstellt wird, oder die Größen von alle der gemeinsam genutzten Bibliotheken nutzen, oder auch die Länge ihrer Namen Datei, können die Ergebnisse stören. Variationen sind klein, aber nicht erwarten perfekt wiederholbare Ergebnisse, wenn Ihr Programm überhaupt ändert.

Neuere GNU/Linux-Distributionen adressieren Raumrandomisierung, in , die identische Läufe des gleichen Programms haben ihre gemeinsamen Bibliotheken geladen an verschiedenen Orten, als Sicherheitsmaßnahme. Dies stört auch die Ergebnisse.

Während diese Faktoren bedeuten, dass Sie nicht vertrauen sollten, dass die Ergebnisse supergenau sind, sollten sie nah genug sein, um nützlich zu sein.