Оптимизация для конвейерного исполнения

В архитектуре конвейера перед выполнением инструкций они разбиты на более мелкие. Так они бегут намного быстрее. Но до того, как инструкция выполнена целиком, невозможно выполнить следующую инструкцию, адресованную тем же регистрам.
Правильно ли это, чтобы оптимизировать порядок инструкций, которые будут обращаться к одному и тому же регистру (или ячейке ОЗУ), чтобы эти инструкции были расположены как можно дальше друг от друга?
Или в этом нет никакого смысла, потому что компилятор сам оптимизирует этот путь?

Например:

int a = 1, b = 2, c = 3;
a *= a;
b *= a;  // stop and waiting for the end of calculating (a)
c *= c;

Оптимизированный:

int a = 1, b = 2, c = 3;
a *= a;
c *= c;  // calculating (a), but we don't need this and don't stop
b *= a;

0

Решение

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

Для порядковых архитектур (например, Cell) порядок команд имеет значение. Однако вполне вероятно, что правильно оптимизирующий компилятор сможет сделать это, переупорядочив его самостоятельно во многих случаях (то есть до тех пор, пока он может доказать, что это не изменит поведение кода). Основными сценариями, в которых это, скорее всего, не удастся, является указатель (или volatile переменные), так как в большинстве случаев компилятор не может доказать, что разные указатели не указывают на одну и ту же переменную. Вещи как __restrict может помочь в этом случае.

Еще один момент, на который следует обратить внимание, заключается в том, что во многих случаях задержка таких вещей, как умножение целых чисел, на самом деле не влияет на время выполнения, поскольку для многих программ производительность более ограничена доступом к памяти. В тех случаях, когда это действительно имеет значение, было бы более полезно подумать об использовании simd и / или многопоточности для оптимизации кода, чем думать о размещении инструкций.

В заключение я бы сказал, что этот вид оптимизации не очень полезен в скомпилированном языке (при написании ассемблера ситуация может быть разной), поскольку как процессор, так и компилятор могут изменить порядок в любом случае, и это может даже не иметь значения , Это не означает, что не бывает ситуаций, когда такая оптимизация полезна, но это действительно только в самых критических путях кода, когда доказано, что компилятор / процессор не справляется с этой задачей.

1

Другие решения

Других решений пока нет …