В одном из своих выступлений, Андрей Александреску, предполагает, что на 64-битной платформе использование 32-разрядной индексации массивов происходит быстрее, чем использование необработанного указателя:
Страница 16: http://www.slideshare.net/andreialexandrescu1/three-optimization-tips-for-c-15708507
На своей учетной записи в Facebook он более точно и говорит: "Предпочитайте индексирование массива указателям (этот, кажется, меняется каждые десять лет).
Я пробовал много вещей, чтобы найти разницу, но мне не удалось создать какую-либо программу, которая показывает эту разницу. Зная Андрея, я не удивлюсь, что разница составляет не более нескольких процентов, но я был бы рад, если бы кто-нибудь нашел такой пример.
Вот тест, который я сделал. Я выбираю n = 5000, достаточно большой, чтобы получить приличное время и достаточно маленький, чтобы все вписывалось в кеш L1. Я петлю несколько раз, чтобы частота процессора повышалась.
#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;
}
Вот такой результат я получаю на своей машине (ядро i7). Все, что я получаю, это "шум".
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