Ich habe folgendes Problem:Warum haben Arrays unterschiedlicher Integer-Größen unterschiedliche Leistung?
Die Schreibzeiten auf ein std::array
für int8
, int16
, int32
und int64
mit jeder Größenzunahme verdoppeln. Ich kann solches Verhalten für eine 8-Bit-CPU verstehen, aber nicht für 32/64-Bit.
Warum benötigt ein 32-Bit-System viermal mehr Zeit zum Speichern von 32-Bit-Werten als zum Speichern von 8-Bit-Werten?
Hier ist mein Testcode:
und meine Ergebnisse sind folgende g++ -o array_issue_1 main.cpp -O3 -std=c++14
Time of processing int8 array: 9922us.
Time of processing int16 array: 37717us.
Time of processing int32 array: 76064us.
Time of processing int64 array: 146803us.
Wenn ich mit -O2
kompilieren, dann Ergebnisse
#include <iostream>
#include <array>
#include <chrono>
std::array<std::int8_t, 64 * 1024 * 1024> int8Array;
std::array<std::int16_t, 64 * 1024 * 1024> int16Array;
std::array<std::int32_t, 64 * 1024 * 1024> int32Array;
std::array<std::int64_t, 64 * 1024 * 1024> int64Array;
void PutZero()
{
auto point1 = std::chrono::high_resolution_clock::now();
for (auto &v : int8Array) v = 0;
auto point2 = std::chrono::high_resolution_clock::now();
for (auto &v : int16Array) v = 0;
auto point3 = std::chrono::high_resolution_clock::now();
for (auto &v : int32Array) v = 0;
auto point4 = std::chrono::high_resolution_clock::now();
for (auto &v : int64Array) v = 0;
auto point5 = std::chrono::high_resolution_clock::now();
std::cout << "Time of processing int8 array:\t" << (std::chrono::duration_cast<std::chrono::microseconds>(point2 - point1)).count() << "us." << std::endl;
std::cout << "Time of processing int16 array:\t" << (std::chrono::duration_cast<std::chrono::microseconds>(point3 - point2)).count() << "us." << std::endl;
std::cout << "Time of processing int32 array:\t" << (std::chrono::duration_cast<std::chrono::microseconds>(point4 - point3)).count() << "us." << std::endl;
std::cout << "Time of processing int64 array:\t" << (std::chrono::duration_cast<std::chrono::microseconds>(point5 - point4)).count() << "us." << std::endl;
}
int main()
{
PutZero();
std::cout << std::endl << "Press enter to exit" << std::endl;
std::cin.get();
return 0;
}
ich es unter Linux mit kompilieren sind 5 mal schlechter für int8
!
Sie können diese Quelle auch in Windows kompilieren. Sie werden eine ähnliche Beziehung zwischen den Ergebnissen erhalten.
Update # 1
Wenn ich mit -O2 kompilieren, dann sind meine Ergebnisse folgende:
Time of processing int8 array: 60182us.
Time of processing int16 array: 77807us.
Time of processing int32 array: 114204us.
Time of processing int64 array: 186664us.
ich nicht Assembler Ausgabe analysieren. Mein wichtigster Punkt ist, dass ich in C++ effizienten Code schreiben möchte und Dinge wie diese zeigen, dass Dinge wie std::array
aus Performanceperspektive herausfordernd und irgendwie kontraintuitiv sein können.
Haben Sie sich den Baugruppenausgang angesehen? –
Ich [schrieb einen Benchmark] (https://github.com/travisdowns/uarch-bench), der unter anderem genau das testet: die Kosten von 'BYTE',' WORD', 'DWORD' und' QWORD' schreiben. Das Ergebnis ist, dass sie alle genau einen Zyklus auf einer modernen Intel-CPU nehmen, außer wenn sie eine Cache-Line-Grenze überschreiten, an welchem Punkt sie zwei Zyklen benötigen. Beachten Sie, dass größere Werte mit höherer Wahrscheinlichkeit eine Cache-Zeilengrenze überschreiten, wenn Sie an bytegranularen Speicherorten nach dem Zufallsprinzip schreiben. In der Praxis wird dieser Benchmark und der meiste Code ausgerichtete Puffer verwenden, so dass Grenzüberschreitungen überhaupt nicht auftreten. – BeeOnRope
Ihr "Hauptpunkt" ist verstümmelt, können Sie es bearbeiten, um klar zu sein? PS: Sie sollten sich keine Sorgen darüber machen, in C++ "effizient" zu sein, außer auf der Ebene der Algorithmen/Bibliothek und der C++ - abstrakten Maschine & ihrer Objekte & Datentypen, bis Sie spezifische Engpässe entdecken und suchen Algorithmus/Datatyp/Objektlevel und dann Allokatoren, alles noch in C++, und wenn Sie sich jemals Gedanken über den Maschinencode machen, sollten Sie das Problem im Maschinencode und nicht in C++ angehen. – philipxy