Какова разница в скорости между индексами и указателями?

Как можно улучшить производительность операции присваивания элементам массива c в зависимости от значений элементов массивов a и b? Есть ли разница в скорости между обращением к элементам массивов через индексы и обращением через указатели? Я провел некоторые тесты на моем компьютере, но мне нужны рекомендации на основе более объективных данных.
  • 3 января 2024 г. 10:51
Ответы на вопрос 2
В контексте языков программирования C и C++, разница в скорости между обращением к элементам массива через индексы и через указатели обычно минимальна или отсутствует. Это потому, что при оптимизации компилятор преобразует индексацию массива в операции, аналогичные тем, что используются при работе с указателями.

Тем не менее, если вы работаете с оптимизацией на очень низком уровне, вам важно понимать, как компилятор преобразует обращение к массиву через индексы и как это сравнивается с доступом через указатели.

Доступ к элементам массива через индексы, как правило, реализуется как операция со смещением относительно начала массива:

```c
int value = array[index];
```

Это преобразуется в нечто вроде:

```assembly
MOV EAX, [EBP + index*4 + offset_of_array]
```

Тогда как работа с указателями происходит напрямую:

```c
int value = *(ptr + index);
```

Это может быть представлено аналогичной инструкцией ассемблера:

```assembly
MOV EAX, [ECX + index*4]
```

Если вы хотите улучшить производительность операции присваивания элементам массива `c` в зависимости от значений элементов массивов `a` и `b`, вот некоторые общие рекомендации:

1. Использование оптимизирующих компиляторов: Современные компиляторы (например, GCC или Clang) могут автоматически оптимизировать код так, чтобы использовать наиболее эффективные инструкции для доступа к массивам.

2. Локализация данных: Обеспечение локализации данных и их последовательности в памяти может уменьшить кэш-промахи и улучшить производительность.

3. Уменьшение количества операций: Минимизация операций внутри циклов, особенно если они могут быть выполнены за пределами цикла.

4. Использование оптимизации циклов: Луп анроллинг (разворачивание циклов) и иные трансформации, которые уменьшают накладные расходы на итерации цикла и позволяют компилятору лучше использовать инструкции SIMD, где это возможно.

5. Параллелизм: Использование потоков или векторизация с помощью инструкций SIMD может ускорить обработку данных, особенно для больших массивов.

6. Избегание условий в горячих путях: Условные переходы внутри циклов могут приводить к плохой предсказуемости ветвлений и замедлять выполнение. Часто лучше структурировать код так, чтобы минимизировать количество условий внутри циклов.

Определенный выбор оптимизации будет во многом зависеть от конкретных требований вашей задачи, архитектуры процессора, компилятора, и может потребовать профилирования и тестирования кода. Для получения более точных рекомендаций по оптимизации, необходимо изучить генерируемый ассемблер
Зависит от модели процессора, версии и опций компилятора и немножечко фазы луны. В целом без разницы. 

Практический совет - лучше писать через индексы, ибо так понятнее и больше шансов что компилятор там все наоптимизирует (например, он сможет векторизовать работу через какие-нибудь SSE инструкции процессора).

Совет по бенчмарку - если памяти не хватает, стоит по одному достаточно большому массиву пройтись 10000 раз. А лучше использовать готовые фреймворки для измерения скорости, вроде того де gbenchmark.

Еще, иногда полезно посмотреть на ассемблерный выхлоп. Вот , например, что происходит при -O3 опции компилятора. Он генерирует вообще идентичный код для обеих функций (развернув циклы)! И даже при -O2 оно одинаковый код выдает.

Без оптимизаций код разный , но в там все не так как вы думаете. Вместо инструкции mov eax, dword ptr [rax + 4*rcx] в варианте с индексами используется инструкция mov eax, dword ptr [rax] для указателей. Это самое "складывание с указателем массива" вообще не отдельная операция - а вариант адрессации в инструкции mov. Они могут вообще одинаковое количество тактов занимать, это надо мануал по конкретной архитектуре процессоров читать.
Похожие вопросы