Ersetzen eines 32-Bit-Schleifenzählers durch einen 64-Bit-Zähler verursacht seltsame Leistungssprünge mit _mm_popcnt_u64 auf Intel-CPUs
Hallo zusammen! Ich schreibe eine hochleistungsfähige Funktion zum Zählen von Einzelbits (popcount) in einem großen Array von 64-Bit-Ganzzahlen. Ich verwende das Intrinsic `_mm_popcnt_u64` aus SSE4.2. Der Code ist einfach – eine Schleife, die den popcount für jedes Element summiert.
Ich habe ein seltsames Verhalten festgestellt: Wenn die Schleifenvariable als `uint32_t` deklariert wird, arbeitet die Funktion sehr schnell. Aber wenn ich sie auf `uint64_t` ändere (einfach durch Ändern des Typs von `i`), fällt die Leistung um fast die Hälfte! Ich habe dies auf mehreren Intel Core i7 (Sandy Bridge, Haswell, Skylake) getestet – der Effekt tritt auf. Der Compiler ist MSVC 2010, obwohl bei GCC 4.6.3 ein ähnliches Bild zu sehen ist. Optimierungen sind aktiviert (/O2 oder -O2).
Hier ist ein minimales Codebeispiel:
```cpp
#include
#include
#include
#include
// Schnelle Version mit 32-Bit-Zähler
uint64_t popcnt32(const uint64_t* data, size_t size) {
uint64_t result = 0;
for (uint32_t i = 0; i < size; ++i) { // <-- 32-bit
result += _mm_popcnt_u64(data[i