За все сказать не могу, но C# нет, а VC да. В любом случае, этот код дан только для простоты иллюстрации концепции, в более сложных случаях оптимизаций не будет, а зависимости останутся.
В идеале должна быть такая оптимизация кода:
<тут кода нет>
Так как переменные нигде больше не используются, то и делать над ними операции, и выделять под них память не нужно :)
В детстве при отладке боролся с оптимизацией путём вывода значений переменных на печать и т.п., иначе компилятор их и все действия над ними игнорировал :)
Delphi блок кода выбрасывает, но при этом выдаёт хинт, что мол у вас тут ненужные операции присутствуют :)
Не работает такая операция только при операциях над данными, доступными извне т.к. такие ситуации нельзя предусмотреть на стадии компиляции.
Очень странные результаты в последнем примере. В Java я не смог добиться такого же результата. На моей машине результаты для трёх случаев составили соответственно: 88ms, 90ms и 41ms.
Увеличил 200.000.000 до 800.000.000 и получил следующее диапазоны (по четыре запуска на каждый из трёх случаев):
(277ms — 286ms); (279ms — 291ms); (133ms — 142ms)
Вы про абсолютное время? Так ведь тачки разные… нельзя тут в лоб сравнивать… я о том, что первые два случая равнозначны, а третий выполняется быстрее, таким образом результат соответствует ожидаемому…
Да, действительно, я когда-то давно читал, а эта статья напомнила мне именно его книгу :) Я бы сказал, что там примеры, демонстирирующие были менее интересными — примеры, как правило, были больше.
В книге очень много железячных подробностей о том, как работает память, кэш и т.д.
Таким вот незамысловатым методом проб и ошибок автор открыл для себя cache line size и особенности работы в SMP, которые тем, кто этим занимается известны давным давно :)
Вообще-то, об это написано в первых же советах по оптимизации алгоритмов на сайте developer.intel.com.
Что касается тестов и оптимизации компилятором, то, как правильно пишется выше в комментах, циклы эти могут распознаться, как бесполезные и тупо могут быть выброшены из финального кода. Просто статиком здесь не поможешь. В конце цикла для надежности неплохо бы поставить хотя бы ASSERT с проверкой требуемого значения — чтобы было зафиксировано обращение к участку памяти — тогда можно и оптимизированный компилером код протестить.
Во многих случаях из реальной жизни эти вопросы, кстати, решаются использованием заточенного под SMP кэширующего bulk-аллокатора памяти, который сам определит размер cache line size и будет действовать соответственно.
По крайней мере обычному программисту обычных задач об этом париться не стоит.
Прогеру работающему в области highload, который использует все свое — аллокаторы, хэш-таблицы, кэшы и т.п. — вот ему это нужно.
Кому что не понравилось в моем комментарии!? еще и карму -2 сняли. я просто хотел сказать что это классная статья. разве важно какими эпитетами и сравнениями я это делаю?
хабрабыдло атакует
1) Выровнять начало массива на границу 16 байт
2) Использовать sse регистр
3) Использовать non-temporary store инструкции
Эффект непосредственно от третьего пункта будет заключаться в невытеснении данных из L2/L3.
То есть, если до стирания экрана в L2/L3 находились данные, которые будут использоваться после стирания экрана — будет ускорение.
зачем заниматься такой низкоуровневой оптимизацией?
где вы видели задачи, когда можно без ущерба для заказчика обсчитывать не каждый элемент массива, а только каждый 16-й?
как вы думаете, не лучше ли просто оптимизировать высокоуровневый алгоритм или вообще заменить его другим, чем пытаться оптимизировать под конкретную модификацию процессора?
вы думаете на fps сильно влияют оптимизации такого уровня?
я считаю что не влияют. на fps в большей степени влияет видеокарта и то, что происходит внутри нее, а не в cpu
не каждая современная игра занимает все (много) ресурсов процессора
Галерея эффектов кэшей процессоров