Помнится, ещё в самом начале 2000-ных мне попалась краткая распечатка программинг-гайдлайнов K6 от AMD. С тех пор, наверное, я стал намного ответственнее подходить к написанию кода.
(здесь много авторитетного мнения о важности оптимизации кода)
Вот современный документ: http://support.amd.com/TechDocs/40546.pdf
Рекомендую, интересное чтение. Можно скипнуть прямо к главе 2 "C and C++ Source-Level Optimizations".
Если у вас есть чем поделиться, выкладывайте сюда.
Всё перечисленное очевидно, за исключением п. 2.2.
Здесь требуется уточнить, что избегать доступа по разыменованию указателя надо только тогда, когда есть реальная возможность по перегруппировке/распараллеливанию инструкций. Если код сугубо последовательный - то доступ по указателю, вообще говоря, быстрее, т.к. доступ без индексного смещения (а в случае больших индексов - ещё и дополнительная операция по расчёту смещения). Кроме того, любой адекватный компилятор должен понимать, что *s и s[0] это одно и то же, и то, что у меня привычка использовать первый вариант - это всего лишь безобидная привычка.
Без оптимизаций - так вообще доступ по указателю гарантированно будет быстрее.
XaeroX писал: а в случае больших индексов - ещё и дополнительная операция по расчёту смещения
Неужели есть какая-то принципиальная разница в быстродействии при складывании больших и малых чисел? Ну вот я складываю два целых числа, одно допустим 5, а другое 3. И что, это будет быстрее чем сложение чисел 236456435 и 326473475? Помоему одинаково - одна операция.
Цитата:
XaeroX писал: Кроме того, любой адекватный компилятор должен понимать, что *s и s[0] это одно и то же, и то
В С++ крайне неудобно организовано изменение многомерного массива, указатель на который передаётся в аргумент функции. Он всё время норовит записать не втуда или вообще создать локальную копию, хотя в чистом Си с этим никогда не было проблем.
Дядя Миша
Я предположил, что в случае, когда индекс выходит за пределы страницы памяти, команда должна как-то это учитывать. В то время как прямая последовательная модификация указателя явно даёт процессору понять, что вот-вот потребуется новая страница в кэше.
Возможно, на современных процессорах и нет разницы.
Lea эффективнее add хотя бы потому, что это разные модули, и lea освобождает арифметический блок для вычислений. Но хороший компилятор сам умеет переводить арифметику указателей на lea/mov, и когда говорят "индексный доступ быстрее доступа по указателю" - это значит, они сами расписываются в проблемах своего компилятора, который что-то умеет плохо. По мне - так нет разницы. Единственная проблема - алиасинг, но это сильно зависит от конкретного алгоритма.
Дядя Миша писал: А современные компиляторы автоматически умеют пихать SSE-апхчимизации. По крайней мере GCC ваш.
Да умеют, но я больше доверяю собственным мозгам в этом плане.
Когда я оптимизирую определённую функцию, я точно знаю, какие у неё будут аргументы, какие результаты мне нужны, а какие нет. Я знаю расположение данных в памяти. Всё это позволяет писать более эффективный SSE-код, чем общее решение "на все случаи жизни" на том же SSE. Конечно, есть и минус - чуть изменил функцию или её прототип, и надо всё переписывать. Поэтому я такие вещи всегда напоследок откладываю, когда все интерфейсы устаканились.
Кармак в дум3 вон вообще каждой функции сделал отдельную SSE-версию.
А вальва написала общие версии - и в итоге они работают медленнее, чем обычные FPU-реализации.
Не, у нее там есть SSE-версии на наиболее критичные функции, типа VectorTransform. И по моему даже указатели на функции, чёб нужную подставлять. Дух функциональщины слабо истребим
А вот если оптимизировать циклы, например, весь cStudioModelRenderer по принципу, который написан в мануале, то даст ли это прибавки к фпс ?
Цитата:
2.14 Explicit Parallelism in Code
Optimization
Where possible, break long dependency chains into several independent chains that can be executed
in parallel to take advantage of the execution units in each pipeline.
Application
This optimization applies to:
• 32-bit software
• 64-bit software
Rationale
It is especially important to break long x87, SSE, or SSE2 dependency chains into smaller executing
units in floating-point code, because of the longer latency of floating-point operations. Most
languages (including ANSI C) are bound by the guarantee that floating-point expressions can not be
reordered; compilers cannot usually perform such optimizations unless they offer a switch to allow
noncompliant reordering of floating-point expressions according to algebraic rules.
Reordered code that is algebraically identical to the original code does not necessarily produce
identical computational results due to the lack of associativity of floating-point operations. There are
well-known numerical considerations in applying these optimizations (consult a book on numerical
analysis). In some cases, reordered floating-point code may lead to unexpected results, but in the vast
majority of cases, the final result differs only in the least-significant bits.
Examples
Avoid
double a[100], sum;
int i;
sum = 0.0f;30 C and C++ Source-Level Optimizations Chapter 2
Software Optimization Guide for AMD Family 10h and 12h Processors 40546 Rev. 3.13 February 2011
for (i = 0; i < 100; i++) {
sum += a[i];
}
Preferred
double a[100], sum1, sum2, sum3, sum4, sum;
int i;
sum1 = 0.0;
sum2 = 0.0;
sum3 = 0.0;
sum4 = 0.0;
for (i = 0; i < 100; i + 4) {
sum1 += a[i];
sum2 += a[i+1];
sum3 += a[i+2];
sum4 += a[i+3];
}
sum = (sum4 + sum3) + (sum1 + sum2);
Notice that the four-way unrolling is chosen to exploit the four-stage fully pipelined floating-point
adder. Each stage of the floating-point adder is occupied on every clock cycle, ensuring maximum
sustained utilization.
XaeroX писал: Прочитай, пожалуйста, весь мой пост, а не выхваченную из контекста фразу.
Какой контекст? Ну ок, я код дума не читал. Просто делюсь наблюдениями.
Цитата:
XaeroX писал: На пентиум-1 - безусловно, пол-фпс выиграешь.
Это ты зря. При тестировании оптимизации кода на системе частиц я выигрывал куда больше. Я думаю, на проце 2ГГЦ можо получить весьма неплохой выигрыш в движке ХЛ1, где всё на проце крутится.
Да и вообще, надо уважать труд инденеров и стремиться к красоте кода.
Честно говоря - нет. Они плохо написали?
Я хотел себе то же самое сделать. Только забил по причине кривости асм-вставок для разных платформ, просто некогда всю эту муть изучать.
Я уже говорил, что после оптимизаций число частиц в кадре мне удалось повысить на ~25%.