In una delle sue note chiave, Andrei Alexandrescu, suggerisce che, su una piattaforma a 64 bit, l'utilizzo dell'indicizzazione di array a 32 bit sia più veloce rispetto all'utilizzo del puntatore raw:Efficienza su una piattaforma a 64 bit: puntatore vs indicizzazione di array a 32 bit
Pagina 16: http://www.slideshare.net/andreialexandrescu1/three-optimization-tips-for-c-15708507
Sul suo account di Facebook, è più preciso e dice: "Preferisco serie indicizzazione ai puntatori (questo sembra invertire ogni dieci anni)".
Ho provato molte cose per trovare una differenza, ma non sono riuscito a creare alcun programma che mostri questa differenza. Conoscendo Andrei, non sarei sorpreso che la differenza non sia superiore a qualche percento, ma sarei felice se qualcuno trovasse un simile esempio.
Ecco un test che ho fatto. Scelgo n = 5000, abbastanza grande da ottenere un timing decente e abbastanza piccolo da far sì che tutto si adatti alla cache L1. I loop alcune volte in modo che la frequenza della CPU aumenti.
#include <iostream>
#include <chrono>
int main(int argc, const char* argv[]) {
const int n{5000};
int* p{new int[n]};
// Warm up the cache
for (int i{0}; i < n; i++) {
p[i] += 1;
}
for (int j{0}; j < 5; j++) {
{
auto start_pointer = std::chrono::high_resolution_clock::now();
for (int* q{p}; q != p + n; ++q) {
++(*q);
}
auto end_pointer = std::chrono::high_resolution_clock::now();
auto time_pointer = std::chrono::duration_cast<std::chrono::nanoseconds>(
end_pointer - start_pointer)
.count();
std::cout << " Pointer: " << time_pointer << std::endl;
}
{
auto start_pointer = std::chrono::high_resolution_clock::now();
for (int* q{p}; q != p + n; ++q) {
++(*q);
}
auto end_pointer = std::chrono::high_resolution_clock::now();
auto time_pointer = std::chrono::duration_cast<std::chrono::nanoseconds>(
end_pointer - start_pointer)
.count();
std::cout << " Pointer: " << time_pointer << std::endl;
}
{
auto start_index_32 = std::chrono::high_resolution_clock::now();
for (int i{0}; i < n; i++) {
p[i] += 1;
}
auto end_index_32 = std::chrono::high_resolution_clock::now();
auto time_index_32 = std::chrono::duration_cast<std::chrono::nanoseconds>(
end_index_32 - start_index_32)
.count();
std::cout << "Index 32: " << time_index_32 << std::endl;
}
{
auto start_index_32 = std::chrono::high_resolution_clock::now();
for (int i{0}; i < n; i++) {
p[i] += 1;
}
auto end_index_32 = std::chrono::high_resolution_clock::now();
auto time_index_32 = std::chrono::duration_cast<std::chrono::nanoseconds>(
end_index_32 - start_index_32)
.count();
std::cout << "Index 32: " << time_index_32 << std::endl;
}
{
const std::size_t n_64{n};
auto start_index_64 = std::chrono::high_resolution_clock::now();
for (std::size_t i{0}; i < n_64; i++) {
p[i] += 1;
}
auto end_index_64 = std::chrono::high_resolution_clock::now();
auto time_index_64 = std::chrono::duration_cast<std::chrono::nanoseconds>(
end_index_64 - start_index_64)
.count();
std::cout << "Index 64: " << time_index_64 << std::endl;
}
{
const std::size_t n_64{n};
auto start_index_64 = std::chrono::high_resolution_clock::now();
for (std::size_t i{0}; i < n_64; i++) {
p[i] += 1;
}
auto end_index_64 = std::chrono::high_resolution_clock::now();
auto time_index_64 = std::chrono::duration_cast<std::chrono::nanoseconds>(
end_index_64 - start_index_64)
.count();
std::cout << "Index 64: " << time_index_64 << std::endl;
}
std::cout << std::endl;
}
delete[] p;
return 0;
}
Ecco il tipo di risultato che ottengo sulla mia macchina (core i7). Tutto quello che ricevo è "rumore".
Pointer: 883
Pointer: 485
Index 32: 436
Index 32: 380
Index 64: 372
Index 64: 429
Pointer: 330
Pointer: 316
Index 32: 336
Index 32: 321
Index 64: 337
Index 64: 318
Pointer: 311
Pointer: 314
Index 32: 318
Index 32: 319
Index 64: 316
Index 64: 301
Pointer: 306
Pointer: 325
Index 32: 323
Index 32: 313
Index 64: 318
Index 64: 305
Pointer: 311
Pointer: 319
Index 32: 313
Index 32: 324
Index 64: 315
Index 64: 303
Considerando l'articolo intendevi taggare queste domande come 'C' o' C++ '? –
Il discorso parla di C++ nel titolo, ma la domanda si riferisce a concetti che sono già in C. Inoltre, il discorso di Andrei si lega alla parte C di C++. Questo è il motivo per cui l'ho etichettato con C. Ma ho aggiunto C++ per un pubblico più ampio. – InsideLoop
Questa è la conferma che stavo cercando. Volevo assicurarmi che il problema del puntatore fosse applicabile agli array di base e non ai * vettori *, ecc. –