Здравствуйте, lpd, Вы писали:
lpd>В моем измерении тоже были ошибки: я компилировал без оптимизатора, а когда подключил оптимизатор он выкинул весь расчет.
lpd>Последовательное сложение с индирекцией оказалось ровно в два раза медленне, чем с индирекцией. Это ожидаемо, т.к. выполняется две инструкции, вместо одной.
А какие у тебя опции оптимизации? Надеюсь включена автовекторизация? )
lpd>Сложение со случайным доступом(и вечным cache-miss) оказалось еще в два раза медленнее, чем с последовательным. Это обозначает верхнюю границу эффективности кэша при доступе к данным, и для меня интересно.
Ну так "в два раза медленнее" — это вроде вполне не плохой результат, не так ли? )
lpd>Относительно причин задержек Java/C# vs C++ думаю, что лишний код присущ JIT-компиляторам, и лишние индирекции часть этой проблемы.
Причины медленности Java и C# можно принципиально разделись на два типа:
1. Слабый оптимизатор (по историческим причинам ориентации на JIT), не позволяющий делать глубокий инлайнинг и прочие сильные оптимизации. Теоретически это исправимо со временем (хотя с учётом остановившегося роста быстродействия процессоров это будет не так просто для случая JIT), но в данный момент времени это именно так.
2. Принципиальные архитектурные особенности. Такие как ориентация на ссылочные данные (я уже не говорю про так называемый "боксинг"), приводящие к той самой косвенности. Принудительные виртуальные функции. Убогая и никчемная интроспекция времени выполнения (рефлексия), вместо эффективной интроспекции времени компиляции (как например в языке D). И ещё множество подобных, но более узкоспециализированных нюансов, общим для которых является то, что их всех нельзя исправить не переделав платформу с нуля. Точнее в Java существует некий механизм (специальный оптимизатор работающий внутри JVM и изменяющий исполнение кода на основание наблюдения за его предыдущими исполнениями) под названием escape-анализ, который пытается частично исправлять ситуацию с излишней косвенностью (перемещая некоторые данные из кучи в стек) и виртуальными функциями (делая вместо виртуального вызова инлайнинг кода конкретного потомка), но он нормально срабатывает только для некоторых редких случаев и то вероятностно (в зависимости от обрабатываемых данных). Так что в целом можно сказать, что указанные проблемы являются принципиально неисправимыми.
Какой из этих типов тормозов вносит больший вклад зависит конечно же от конкретного кода. Но я сомневаюсь, что в большинстве случаев главной причиной является тип1 (как по сути утверждал тут ты).
lpd>Однако, программируя на C++, очень редко есть смысл заботиться об индирекции, т.к. далеко не все функции в программе занимают значительное время.
Если программировать в стиле нормального современного C++, то ни о чём заботиться и не надо — всё будет происходить автоматически. Кстати, это как раз одно из главных и старейших преимуществ C++, что программа написанная без всяких специальных оптимизаций (но в каноническом стиле) будет при этом исполняться на близких к максимальным уровнях производительности. Но это главную возможность очень легко сломать, если перейти от программирования в стиле канонического C++ к стилю Java (компилятор C++ же легко позволяет и такое, но вот быстродействие в таком случае уже никто обещать не будет).
lpd>Вообще, C++ быстр сам по себе и программа будет работать быстрее, чем C#/Java, в любом варианте.
Это не так. Смотри хотя бы предыдущий абзац.