Есть ли основные правила супер оптимизации?
=============================================

 Есть ли правила, которых рекомендуют придерживаться для оптимизации? 

 Есть развернутый ответ для С++ кода, но его можно обобщить и на другие языки и платформы:  
  

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

1) Важно понимать, что алгоритмическая оптимизация практически всегда может дать лучший эффект, чем программная. Так, если алгоритм имеет сложность O(n^2), то на больших исходных данных он при любой оптимизации будет медленнее, чем неоптимизированный алгоритм сложности O(n). Впрочем, при выборе алгоритма, опираться только на его сложность не стоит: если объем исходных данных не велик, то вполне может оказаться, что алгоритм со сложностью O(n^2) будет работать быстрее, чем с O(n).  

2) Очень важно повторное использование (кеширование) промежуточных данных, вычисленных в программе – ибо быстрее всего выполняется работа, которую не надо делать. Тем не менее, не надо чрезмерно кешированием увлекаться – если объем кэшируемых данных слишком велик, то это может отрицательно сказаться на общей производительности программы (некоторые данные быстрее вычислять на лету, чем считывать из памяти).  

3) Следует избегать излишнего копирования данных (например, передавать сложные типы данных по ссылке, а не по значению).  

4) По возможности следует избегать условных операторов во вложенных циклах. Так как условные переходы, вызываемые такими операторами, плохо обрабатываются современными процессорами с конвейерной архитектурой.  

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

6) Если алгоритмы это позволяют, то возможно стоит реализовать их параллельное исполнение (в отдельных потоках или процессах). Это позволит эффективно задействовать современные многоядерные процессы.  

7) В некоторых случаях (например обработка изображений) большого эффекта можно достичь применением специализированных расширений процессора (SSE, SSE2, AXX, AVX2 и другие). Стоит отметить, что большинство современных компиляторов (GCC, MSVS, ICC) поддерживают непосредственное использование данных расширений непосредственно из С++ кода при помощи специальных встроенных функций (intrinsics). Минусами такого подхода является потеря переносимости (впрочем, эта проблема решается наличием разных веток программы под разные процессоры) и значительное усложнение программы.  

8) Также большого эффекта можно достичь применением специализированных ускорителей, например GPU (технологии CUDA, OpenCL). Минусами таких решений являются потеря универсальности и значительное усложнение программы, а также то, что на специализированных ускорителях, как правило, хорошо работает далеко не каждый алгоритм. 

 Главное правило оптимизации - не заниматься преждевременной оптимизацией.  
  

Вообще все просто - пишите код, пишите нагрузочные тесты, профилируете, оптимизируете узкие места. С опытом ляпов будет меньше изначально. Ну и книжки стоит читать всякие, желательно обобщенные (типа там паттерны проектирования и т.д.) что бы можно было вместо оптимизации просто быстро систему масштабировать (это дешевле). Ну и еще теория алгоритмов помогает, если у вас есть именно обработка больших объемов данных (массивы на миллионы айтемов, на тысячах пофигу обычно) 

 Разбираетесь как работает память, проц, диск - узнаете про архитектуру, про виды памяти, про кеши и синхронизацию.   

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

Разбираетесь как работает программа которую оптимизируете - профилируете, исправляете уже с учетом полученных знаний из первых двух пунктов.  
  

По другому никак. Без знаний оптимизацией не занимаются. 

 Тут хорошо ответили про оптимизацию написанного приложения и про то, что не надо с ней торопиться. Но также очень важно **до начала** написания кода правильно спроектировать архитектуру вашей системы. На задачах какого масштаба она будет использоваться? В каком окружении она будет работать? Какие требования к отказоустойчивости и резервированию?  
  

Все эти ответы могут существенно повлиять на архитектуру решения. Например, если вы пишете код, заточенный под работу в носимом девайсе на конкретном ARM-процессоре (какой-нибудь очередной умный браслет) – вы можете применить одни подходы (изучить железо, оптимизировать под него на низком уровне). А если вы делаете коробочный продукт, который будет работать в гетерогенной среде (например, антивирус, который запустят на самых разных машинах и системах) – то вам становится важнее добиться надежности и производительности "в среднем".  
  

Аналогично, если вы делаете софт, запускающийся в один поток на одном компьютере – это одно, а если проектируете систему, которая будет работать параллельно на десятках ядер на сервер и сотнях этих серверов, стоящих в одном дата-центре – совсем другое (а если не в одном, а в разных дата-центрах, то вообще третье). 

 Главный вопрос - а что мы оптимизируем? Память? Скорость? Размер программы? Легкость модификации? Тут как в RPG - качаем силу, персонаж тупеет; Увеличили скорость - сожрали кучу памяти. И так далее. 

[ruhighload.com](http://ruhighload.com/) 

[kPHP](https://ru.wikipedia.org/wiki/KPHP) 

 Перформанс можно еще выжать из компилятора, поигравшись флажками. Для начала можно попробовать O2, а потом и LTO (IPO). Но, вырастет compile-time.   

Если алгоритм параллельный, как отмечали предыдущие отвечающие, можно использовать OpenMP. Новые версии стандарты поддерживают и явную векторизацию и оффлоад на ускоритель.  

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