Re[40]: benchmark
От: alex_public  
Дата: 11.01.17 21:25
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Неплохой, однако в типичной серверной/десктопной/системной программе на C++(мы вроде не говорим на вычислениях) редко встречается последовательный доступ к большим векторам, да еще с минимальной обработкой. Ясно, что в редких случаях, вроде обработки запроса из кэша баз данных(например) доступ последовательный, но и там temportal кэширование важнее, чем spatial. Поэтому я бы не сказал, что однозначно всегда лучше хранить в векторе объекты, чем указатели. Т.к. обычно это вопрос архитектуры, или избежания копирования, а не оптимизации кэша. Хотя, случаи разные, — это понятно.


Лишняя косвенность — это плохо всегда. И не только для массивов и кэша. См. например в конце этого сообщения.

lpd>Я не исследовал JVM, но могу предположить, что байт код отличается от внутреннего представления программы компилятором, поэтому он вносит дополнительные сущности, которые потом сложно соптимизировать. Это всего лишь мое предположение.


Это не всегда так. Попробуй скомпилировать своё C++ приложение в llvm и потом запустить его под JIT. )

lpd>Однако, я думаю, что низкая производительность присуща любому языку, преобразуемому в промежуточный байт-код. Иначе давно бы Java, C# или другой подобный язык догнал по скорости C++(правда, я все равно считал бы, что байт-код по сути является не нужным усложнением).


Java, C# и т.п. никогда не смогут догнать C++, ни при каком оптимизаторе и формате исполняемого файла (есть же компиляторы C# в машинные кода) совсем по другими причинам. И я описывал их в предыдущем сообщение. Ну вот смотри, разберу одну из этих причин на пальцах для примера:

Ты же наверняка знаешь, что во всех этих языках все методы являются виртуальными функциями (говоря языком C++). Что это значит с точки зрения оптимизации? Что компилятор (пусть он даже очень сильный и у него есть куча времени) физически не сможет сделать инлайнинг, потому что просто не знает какой конкретно код в реальности будет вызываться — это определяется только в рантайме. В то время как в C++ не только часто употребимы не виртуальные функции, но и для виртуальных компилятор гарантированно осуществляет инлайнинг, если они вызваны от обычной переменной (а не от указателя или ссылки).
Re[41]: benchmark
От: lpd Черногория  
Дата: 11.01.17 21:39
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Здравствуйте, lpd, Вы писали:


lpd>>Однако, я думаю, что низкая производительность присуща любому языку, преобразуемому в промежуточный байт-код. Иначе давно бы Java, C# или другой подобный язык догнал по скорости C++(правда, я все равно считал бы, что байт-код по сути является не нужным усложнением).


_>Java, C# и т.п. никогда не смогут догнать C++, ни при каком оптимизаторе и формате исполняемого файла (есть же компиляторы C# в машинные кода) совсем по другими причинам. И я описывал их в предыдущем сообщение. Ну вот смотри, разберу одну из этих причин на пальцах для примера:


_>Ты же наверняка знаешь, что во всех этих языках все методы являются виртуальными функциями (говоря языком C++). Что это значит с точки зрения оптимизации? Что компилятор (пусть он даже очень сильный и у него есть куча времени) физически не сможет сделать инлайнинг, потому что просто не знает какой конкретно код в реальности будет вызываться — это определяется только в рантайме. В то время как в C++ не только часто употребимы не виртуальные функции, но и для виртуальных компилятор гарантированно осуществляет инлайнинг, если они вызваны от обычной переменной (а не от указателя или ссылки).


Не берусь ничего по этому вопросу утверждать — я им мало интересовался, т.к. считаю Java/C# тупиковой ветвью CS, а байт код и его оптимизацию не нужными.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[39]: benchmark
От: lpd Черногория  
Дата: 11.01.17 21:41
Оценка:
Здравствуйте, pilgrim_, Вы писали:

_>Здравствуйте, lpd, Вы писали:


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


_>Вероятно сильно зависит от железа (проц? размер кэшей ?), но разница может доходить и до порядка:


_>...


Мы не знаем, на какой конфигурации в данном случае запускается, и в каких условиях работает. Я запускал на i7-6500U. Мой результат не изменяется при увеличении массива до 1млрд. intов чтобы он ни в какой кэш точно не поместился.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 11.01.2017 21:42 lpd . Предыдущая версия .
Re[41]: benchmark
От: pilgrim_ Россия  
Дата: 11.01.17 21:55
Оценка: 3 (1) +2
Здравствуйте, alex_public, Вы писали:

_>Ты же наверняка знаешь, что во всех этих языках все методы являются виртуальными функциями (говоря языком C++). Что это значит с точки зрения оптимизации? Что компилятор (пусть он даже очень сильный и у него есть куча времени) физически не сможет сделать инлайнинг, потому что просто не знает какой конкретно код в реальности будет вызываться — это определяется только в рантайме.


Выделенное для C# неверно, виртуальность указывается либо явно как в C++, либо неявно при реализации интерфейса.


_>В то время как в C++ не только часто употребимы не виртуальные функции, но и для виртуальных компилятор гарантированно осуществляет инлайнинг, если они вызваны от обычной переменной (а не от указателя или ссылки).


Если под выделенным ты имел ввиду не инлайнинг, а прямой вызов функцуии, то .NEt JIT умеет такое делать.
на данный момент .NEt jit такое делать не умеет: http://rsdn.org/forum/flame.comp/6687499.1
Автор: pilgrim_
Дата: 04.02.17
Отредактировано 04.02.2017 0:30 pilgrim_ . Предыдущая версия .
Re[38]: benchmark
От: Evgeny.Panasyuk Россия  
Дата: 11.01.17 23:34
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Во-первых, как я понял, ты пытаешься измерить задержки из-за cache-miss с помощью listа.


cache-miss'ы будут и в случае vector<int*> и в случае list<int>.
В случае с list<int> помимо cache-miss'а добавляется зависимость по данным — чтобы узнать адрес следующего узла, надо загрузить предыдущий и так далее — поэтому он и медленнее на два порядка, а не на один как vector<int*>.
Подобная зависимость по данным создаётся и в управляемом коде, где чтобы обратиться к полю под-объекта ... под-объекта объекта нужно сделать похожий забег по указателям, разве что цепочки не такие длинные.

Кстати, чтобы исключить эти cache-miss, достаточно закомментировать все сортировки — тогда получается следующий расклад:
* массив указателей в 2.5 раза медленее
* список медленее на порядок

lpd>Думаю, что это не очень хороший подоход,


Не очень хороший подход это компилировать без оптимизатора, а я сделал тест во вполне конкретных условиях, которые нисколько не скрывал

lpd>т.к. элементы list могут быть расположены в памяти последовательно.


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

lpd>В моем же тесте, я точно обращаюсь к элементам в случайном порядке.


Я вообще-то сравниваю ТРИ варианта — в случае vector<int*> — как раз идёт обращение в случайном порядке

lpd>Во-вторых, ты измеряешь производительность stl контейнеров, а не процессора.


ШТА? Я уже выше привёл вывод ассемблера:
.L152:
    mov    rcx, QWORD PTR [rax]
    add    rax, 8
    add    edx, DWORD PTR [rcx]
    cmp    rsi, rax
    jne    .L152
Или другой пример:
.L152:
    add    edx, DWORD PTR [rax]
    add    rax, 4
    cmp    rcx, rax
    jne    .L152

Покажи где тут "производительность stl контейнеров"
Итератор vector'а это по сути указатель, и даже если над ним тонкая обёртка в виде класса, то он всё равно оптимизируется в итоге до обычного указателя.
Или думаешь например там список как-то криво реализован с дополнительными индерекциями?
Я могу конечно всё расписать в рукопашную (и сравнить ASM выхлоп, который скорей всего будет идентичным), но пока не вижу в смысла

lpd>Результаты изменились:

lpd>Последовательное сложение с индирекцией оказалось ровно в два раза медленне, чем с индирекцией. Это ожидаемо, т.к. выполняется две инструкции, вместо одной.

Ты опять меряешь в инструкциях
У тебя результат в примерно два раза медленней потому что тебе нужно перелопатить в два раз больший объём памяти, а алгоритм memory bandwidth bounded. Вместо одного массива, нужно выкачать два (причём одинакового размера). Замени массив четырёх-байтных индексов на массив восьми-байтных — и получишь другое соотношение, при том же количестве инструкций

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


Приведи конкретные цифры, в какой среде запускаешь, какие опции и т.п. Заполни map2 возрастающей последовательностью, а потом перетасуй std::random_shuffle — так чтобы у тебе гарантированно был обход всего массива.
Отредактировано 11.01.2017 23:41 Evgeny.Panasyuk . Предыдущая версия .
Re[27]: Visual C# vs C++. Надо сравнить перспективы.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.17 07:56
Оценка:
Здравствуйте, TK, Вы писали:

TK>Здравствуйте, Serginio1, Вы писали:


_>>>В случае C# мы просто имеем отсутствие этих самых библиотек для всех платформ кроме винды.

S>>А как же .Net Core?

TK>А ее даже под виндой испрльзовать стремно. Кстати, что там с поддежкой winxp или iot девайсов?


Используется в Asp.Net Core и мною в 1С. Все там нормально.
Ты еще Win 95 вспомни. Насчет девайсов есть Tizen и развивается для arm.
Плюс весной выйдет .Net Core 1.2 и NetStandard2
и солнце б утром не вставало, когда бы не было меня
Re[27]: Visual C# vs C++. Надо сравнить перспективы.
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.17 08:03
Оценка:
Здравствуйте, AlexRK, Вы писали:

ARK>Здравствуйте, Serginio1, Вы писали:


_>>>В случае C# мы просто имеем отсутствие этих самых библиотек для всех платформ кроме винды.

S>>А как же .Net Core?

ARK>Хосспади, вы про этот долбаный великолепный .Net Core пишете в каждом посте.

ARK>Нет его по факту нигде, и не факт, что вообще будет. А если что-то и будет, то по производительности все равно будет хуже, чем С++.

Есть в Asp.Net Core и мною в 1С. Плюс весной выйдет .Net Core 1.2 и NetStandard2.

По производительности то развивается .Net Native, развивается Roslyn
Optimising LINQ
roslyn-linq-rewrite

Плюс развивается направление по созданию объектов на стеке, использования нативной памяти без копирования итд.
Именно .Net Core коим по сути и UWP является развивается достаточно мощно
http://rsdn.org/forum/dotnet/6660816.flat
Автор: Sinix
Дата: 09.01.17
и солнце б утром не вставало, когда бы не было меня
Re[41]: benchmark
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.17 08:08
Оценка: 1 (1)
Здравствуйте, alex_public, Вы писали:


_>Ты же наверняка знаешь, что во всех этих языках все методы являются виртуальными функциями (говоря языком C++). Что это значит с точки зрения оптимизации? Что компилятор (пусть он даже очень сильный и у него есть куча времени) физически не сможет сделать инлайнинг, потому что просто не знает какой конкретно код в реальности будет вызываться — это определяется только в рантайме. В то время как в C++ не только часто употребимы не виртуальные функции, но и для виртуальных компилятор гарантированно осуществляет инлайнинг, если они вызваны от обычной переменной (а не от указателя или ссылки).


Дааааа. Я ведь тебе даю ссылки на инлайнинг, на вызов методов .Net из натива и наоборот. Ты хоть читаешь мои посты?

Еще раз уже сейчас в Net Native оптимизация может происходить на двух этапах
1.оптимизация при компиляция в ил Optimising LINQ
roslyn-linq-rewrite

2.Оптимизация при компиляции в натив по аналогии с LLVM

Плюс развивается направление по созданию объектов на стеке, использования нативной памяти без копирования итд.
Именно .Net Core коим по сути и UWP является развивается достаточно мощно
http://rsdn.org/forum/dotnet/6660816.flat
Автор: Sinix
Дата: 09.01.17
и солнце б утром не вставало, когда бы не было меня
Re[33]: «Собаку съел»
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 12.01.17 08:13
Оценка:
Здравствуйте, vdimas, Вы писали:

V>Здравствуйте, Serginio1, Вы писали:


S>> Это же все можно делать и в C# это же Func<X,Y>


V>Ну, дык, статически диспетчеризируемую полиморфную операцию сравнения не сделать.

V>Только динамически через экземпляр IComparer<T> или через ручной copy&paste с целью ad-hoc полиморфизма.

V>Причем, там же рядом я писал:

V>

V>Понятно, что x => x.Y выглядит тривиально, это был лишь пример. В общем случае "оно" может быть не тривиальным, т.к. именно под нетривиальные объемы кода пишут те самые шаблоны "многоразового применения" — в этом их фишка.


V>Это всё к тому, что твой пример с copy&paste вот этого:

V>
V>where(x => x > q)
V>

V>в общем случае является плохой практикой.
V>Но язык позволяет только такую.

Чем это плохо? В С++ зря штоли ввели Лямбды?
Нет язык позволяет использовать

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)


То есть я могу использовать любой дженерик делегат .
Просто лямбды удобнее как для написания так и для чтения, а так же для оптимизации компиляции
и солнце б утром не вставало, когда бы не было меня
Re[39]: benchmark
От: lpd Черногория  
Дата: 12.01.17 08:41
Оценка: 2 (1)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

Заполни map2 возрастающей последовательностью, а потом перетасуй std::random_shuffle — так чтобы у тебе гарантированно был обход всего массива.

Сделал random_shuffle индекса, и результат изменился(не могу сказать почему). Для массива размера 10^8:

19404785ns // последовательный прямой доступ
50612231ns // последовательный доступ с индирекцией
1443553897ns // случайный доступ с индирекцией


Получается заметная разница скорости в 30 раз. Соглашусь, что ее нужно учитывать — в тех случаях, когда доступ последовательный и когда задержки обращения к памяти вносят значительный вклад в общее время. Однако, если говорить о типичных клиент-серверных приложениях на C#/Java, то там подобное встречается не столь часто, и temporal cache все же полезнее, чем spatial.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[25]: Visual C# vs C++. Надо сравнить перспективы.
От: itslave СССР  
Дата: 12.01.17 10:18
Оценка:
Здравствуйте, alex_public, Вы писали:

_>В случае C# мы просто имеем отсутствие этих самых библиотек для всех платформ кроме винды.

Это не так. Вот тебе: https://www.microsoft.com/net/download/core под винду макось и линукс.

_>На мой взгляд это весьма разный уровень кроссплатформенности. )))

На мой взгляд, .NET Core сырой и качество реализации ну просто не фонтан. Я же не ожидал подобных косяков в С++, в котором кроссплатформенность с рождения, более 40 лет.
Re[27]: Visual C# vs C++. Надо сравнить перспективы.
От: itslave СССР  
Дата: 12.01.17 10:24
Оценка:
Здравствуйте, AlexRK, Вы писали:


ARK>Хосспади, вы про этот долбаный великолепный .Net Core пишете в каждом посте.

ARK>Нет его по факту нигде, и не факт, что вообще будет. А если что-то и будет, то по производительности все равно будет хуже, чем С++.
Хосспади, вы про эту про эту долбаную производительности числодробилок заманали писать в каждом мосте. Не нужна эта производительность в реальной жизне чуть менее чем никогда. Понимаешь — оно не нужно, даже забесплатно.
Re[27]: Visual C# vs C++. Надо сравнить перспективы.
От: itslave СССР  
Дата: 12.01.17 10:25
Оценка:
Здравствуйте, TK, Вы писали:

TK>Кстати, что там с поддежкой winxp или iot девайсов?

Не нужно.
Re[42]: benchmark
От: itslave СССР  
Дата: 12.01.17 10:31
Оценка: +1 :))
Здравствуйте, lpd, Вы писали:

lpd>т.к. считаю Java/C# тупиковой ветвью CS, а байт код и его оптимизацию не нужными.

Я вот например в балете не разбираюсь и технику танцевания Майи Плисецкой вообще никогда не комментирую.
Отредактировано 12.01.2017 10:32 itslave . Предыдущая версия .
Re[43]: benchmark
От: lpd Черногория  
Дата: 12.01.17 10:42
Оценка: :)
Здравствуйте, itslave, Вы писали:

I>Здравствуйте, lpd, Вы писали:


lpd>>т.к. считаю Java/C# тупиковой ветвью CS, а байт код и его оптимизацию не нужными.

I>Я вот например в балете не разбираюсь и технику танцевания Майи Плисецкой вообще никогда не комментирую.

C#/Java это продукт двух корпораций(Sun и MS), которые создали hype и повели за собой все ИТ-компании — не более.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Отредактировано 12.01.2017 10:46 lpd . Предыдущая версия . Еще …
Отредактировано 12.01.2017 10:45 lpd . Предыдущая версия .
Re[44]: benchmark
От: itslave СССР  
Дата: 12.01.17 11:02
Оценка: 1 (1) +1
Здравствуйте, lpd, Вы писали:

lpd>>>т.к. считаю Java/C# тупиковой ветвью CS, а байт код и его оптимизацию не нужными.

I>>Я вот например в балете не разбираюсь и технику танцевания Майи Плисецкой вообще никогда не комментирую.

lpd>C#/Java это продукт двух корпораций(Sun и MS), которые создали hype и повели за собой все ИТ-компании — не более.

Да, твое высоковалифицированное экспертное мнение очень важно для всех читателей этого форума.
Re[45]: benchmark
От: lpd Черногория  
Дата: 12.01.17 11:07
Оценка:
Здравствуйте, itslave, Вы писали:

I>Здравствуйте, lpd, Вы писали:


lpd>>>>т.к. считаю Java/C# тупиковой ветвью CS, а байт код и его оптимизацию не нужными.

I>>>Я вот например в балете не разбираюсь и технику танцевания Майи Плисецкой вообще никогда не комментирую.

lpd>>C#/Java это продукт двух корпораций(Sun и MS), которые создали hype и повели за собой все ИТ-компании — не более.

I>Да, твое высоковалифицированное экспертное мнение очень важно для всех читателей этого форума.

Я в ходе обсуждения привел ряд аргументов, и мог бы привести еще при желании. Ты, похоже, всю жизнь программировал только на C# и просто не в курсе, что код может не тормозить. Можешь оставаться при своих заблуждениях.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[34]: «Собаку съел»
От: vdimas Россия  
Дата: 12.01.17 11:57
Оценка:
Здравствуйте, Serginio1, Вы писали:

V>>Это всё к тому, что твой пример с copy&paste вот этого:

V>>
V>>where(x => x > q)
V>>

V>>в общем случае является плохой практикой.
V>>Но язык позволяет только такую.
S> Чем это плохо?

Тем, вестимо, что в каждом конкретном месте можно допустить ошибку.
По сей причине и рождается "матрица специализаций", типа этой.
По ссылке автогенерённый код. В этом смысле С++ позволяет выполнять такую кодогенерацию прямо в исходниках.


S>В С++ зря штоли ввели Лямбды?


Моя рука потихоньку тянется к лицу. ))

Давай сделаем паузу и посмотрим на это всё повнимательней. Лямбды хороши исключительно и только для уникальных случаев, в этом и состоит их ЦЕЛЕВАЯ фишка — они же захватывают текущий контекст! Т.е., твоё x => x > q — это ж вовсе не лямбда (вот почему рука дрогнула в направлении лица), это ж у тебя просто некая "маленькая процедура", которая использует возможность локального объявления процедур (лямбд), не используя при этом их основной механизм. Вполне же можно было объявить такой предикат вне контекста использования, верно? Т.е., получилась лишь некая экономия сугубо на "оформлении" такого предиката в виде отдельной ф-ии.

Т.е., речь о том, что неуникальный случай в C# описать не так-то просто (тем паче с должной эффективностью).


S>Нет язык позволяет использовать

S>
S>public static IEnumerable<TSource> Where<TSource>(
S>    this IEnumerable<TSource> source,
S>    Func<TSource, bool> predicate
S>)
S>

S>То есть я могу использовать любой дженерик делегат .

Не можешь. В теле дотнетной лямбды происходит автовывод типов, поэтому ты вызываешь методы конкретных типов. А для реализации предиката в виде генерика исходные типы должны поддерживать некие данные ЗАРАНЕЕ ограничения на шаблонах или использовать т.н. "объекты-словари операций", навроде IComparer<T>, который в свою очередь может оперировать лишь типами, над которыми ПРЕДВАРИТЕЛЬНО заданы некие ограничения в виде опять и снова интерфейсов.


S>Просто лямбды удобнее как для написания так и для чтения, а так же для оптимизации компиляции


Конечно удобны. Но я на это тоже уже отвечал заранее:

Понятно, что x => x.Y выглядит тривиально, это был лишь пример. В общем случае "оно" может быть не тривиальным, т.к. именно под нетривиальные объемы кода пишут те самые шаблоны "многоразового применения" — в этом их фишка.

С++ позволяет комбинировать технику шаблонов и лямбд, используя каждую из техник по прямому назначению, т.е. заставляя их выполнять исключительно "свою" часть работы.
Отредактировано 12.01.2017 12:00 vdimas . Предыдущая версия .
Re[46]: benchmark
От: itslave СССР  
Дата: 12.01.17 12:04
Оценка:
Здравствуйте, lpd, Вы писали:


lpd>Я в ходе обсуждения привел ряд аргументов, и мог бы привести еще при желании.

Твои аргументы смехотворны. О чем можно говорить, если Java & C# неуклонно выжимают(точней уже выжали) С++ в экзотику. И так уже более 20 лет. Возьми статистику. Мнение анонима из интернета против тысяч общедоступных фактов, о чем тут говорить.

lpd>Ты, похоже, всю жизнь программировал только на C# и просто не в курсе, что код может не тормозить. Можешь оставаться при своих заблуждениях.

И опять громко в лужу. С ужасом вспоминаю времена программирования на С++, медитаций над килобайтными ошибками компиляции, Segmentation Failed и прочими прекрасными результата простреливания себе ноги. А, еще за джунами нужен был глаз да глаз, любой кривой delete мог положить апликуху в раз. И да, на C# у меня ничего не тормозит, задроства красноглазиков с числодробилками меня только улыбают.
Отредактировано 12.01.2017 12:05 itslave . Предыдущая версия .
Re[40]: benchmark
От: Evgeny.Panasyuk Россия  
Дата: 12.01.17 12:07
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Заполни map2 возрастающей последовательностью, а потом перетасуй std::random_shuffle — так чтобы у тебе гарантированно был обход всего массива.

lpd>Сделал random_shuffle индекса, и результат изменился(не могу сказать почему).

Изменился от того что генератор случайных чисел который ты использовал выдавал мало рандомности и видимо попадал в короткий цикл.
Если проверить:
        for_each(map2 + 0, map2 + SIZE, [](auto x){ map1[x] = 0; });
        auto hit_count = count(map1 + 0, map1 + SIZE, 0);
        cout << "hits=" << 100.*hit_count/(SIZE) << "%" << endl;

то оказывается что hits=0.1% — то есть пробежка была только по одной тысячной (!) от всех элементов, соответственно без проблем кэшировалось.
При таком количестве попаданий даже если брать самый экстремальный расклад когда каждый элемент лежит в своей кэш-линии (на современном железе кэш линия обычно 64 байта), то получается что достаточно кэша размером 0.1% * (размер_кэш_линии / sizeof(int32)) = 0.1% * 16 = 1.6% от размера массива.

lpd>Для массива размера 10^8:

lpd>

lpd>19404785ns // последовательный прямой доступ
lpd>50612231ns // последовательный доступ с индирекцией
lpd>1443553897ns // случайный доступ с индирекцией

lpd>Получается заметная разница скорости в 30 раз.

В 30 раз это только если сравнивать два вида индерекции, но речь то изначально шла про индерекции против прямого доступа — для такого случая по твоим числам получается 74x
И это только одна индерекция, в реальности их будет больше, да ещё и с зависимостью по данным как в списке: array.sub_object.sub_object.field

lpd>Соглашусь, что ее нужно учитывать — в тех случаях, когда доступ последовательный и когда задержки обращения к памяти вносят значительный вклад в общее время. Однако, если говорить о типичных клиент-серверных приложениях на C#/Java, то там подобное встречается не столь часто


Встречается часто, и вносят значительный вклад, но для типичных корпоративных "операционных дней" и "всё в базу упирается" это действительно не критично.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.