Интересный пример. Из-за того, что сырые массивы могут частично налагаться друг на друга, векторизация может не сработать. std::array, в свою очередь, гарантирует, что объекты не перекрываются (так как его нельзя сделать из сырого указателя).
Было бы интересно найти пример, в котором веткоризирующих инструкций нет вовсе в случае с указателями, но есть в случае с std::array. Попробую таким заняться.
Да! Плюсы круты в том числе тем имхо, что всегда можно посмотреть на то, что конкретно будет исполнятся.
ЗЫ: знаю одного толкового джуна, который попал в одну плюсерскую команду написав потрясающее сопроводительное письмо о том, как он хочет научится владеть ч0рной магией и быть колдуном)
Вы только что написали заклинание вызова холивара в комментариях))
Не ради холивара, но ради интересной беседы:
1) Стоит разделять оверхед в рантайме и компайлтайме. Многие абстракции никак не zero-cost когда речь доходит до размера объектников и времени компиляции.
2) Даже говоря о рантайме, не всё в плюсах бесплатно. Понимание цены абстракции и её отношение к бенефитам, которые эта абстракция несёт, важно. Наши примеры (std::array и ranged-for), наверное, можно назвать примерами zero-cost, во всяком случае в релизном рантайме. Поэтому они так показательны. Но, например, тут можно послушать про очень интересный пример о std::unique_ptr и о том, как он не бесплатен по отнешению к сырым указателям.
Из ассемблерного кода видно, что, действительно, в оптимизированной сборке на месте вызова operator[] стоит расчёт индекса и доступ к элементу, то есть код идентичнен коду для С масисва. Мне кажется, вам придётся показать, что в релизных сборках такого встраивания может не быть для того, чтобы показать не эквивалентность примеров.
Отпишу сначала про предсказатель, потом про косвенность в следующем комментарии.
Касательно подобных железных вещей практической экспертизой я похвастать не могу, конечно. Но. Если правильно понимаю, современные архитектуры не поддерживают инструкции, напрямую влияющие на предсказатель, в этом вы безоговорочно правы. Так же вы безоговорочно правы и касательно генерации кода - использование указанной интриники может привести к реорганизации кода. При этой реорганизации, например, инструкции двух ветвей условного оператора могут быть поменяны местами. Эта перестановка, в свою очередь, может повлиять на то, какую ветвь исполнения предсказатель выберет за наиболее вероятную.
Хорошее замечание! "Exception specification" проверяется в конце personality routine (обычно), ровно так же, как и сам брошенный эксепшн, то есть через type_info.
А noexcept также оптимизирует код, так как убирает lsda из функции, вызывающей noexcept функцию. Вот тут дали ссылку на обалденный доклад, в котором говорится, что это прирост к перформансу не слишком большой, правда.
Хорошее описание UB! Есть отличное видео как раз об этом.
Интересный пример. Из-за того, что сырые массивы могут частично налагаться друг на друга, векторизация может не сработать.
std::array
, в свою очередь, гарантирует, что объекты не перекрываются (так как его нельзя сделать из сырого указателя).Было бы интересно найти пример, в котором веткоризирующих инструкций нет вовсе в случае с указателями, но есть в случае с std::array. Попробую таким заняться.
Я достаточно далёк от сферы МК. У вас можно профилировтаь и бенчмаркать?
Ловите.
Прикол в том, что в случае с std::unique_ptr практически всегда возникает косвенная адресация при передаче его в функции.
Да, всё верно, спасибо, что заметили! Глаз замылился, сейчас поправлю.
Согласен, полагаться на оптимизации компиляторора в общем случае нужно осторожно. Но в статье описан очень конкретный случай.
Это нюсанс, а котором я не подумал! Большое спасибо, что подсветили!
Да! Плюсы круты в том числе тем имхо, что всегда можно посмотреть на то, что конкретно будет исполнятся.
ЗЫ: знаю одного толкового джуна, который попал в одну плюсерскую команду написав потрясающее сопроводительное письмо о том, как он хочет научится владеть ч0рной магией и быть колдуном)
Кстати, к питону отсылки отличные. Те же итертулз в нём - отпадная вещь, пользоваться которой крайне приятно!
Вы только что написали заклинание вызова холивара в комментариях))
Не ради холивара, но ради интересной беседы:
1) Стоит разделять оверхед в рантайме и компайлтайме. Многие абстракции никак не zero-cost когда речь доходит до размера объектников и времени компиляции.
2) Даже говоря о рантайме, не всё в плюсах бесплатно. Понимание цены абстракции и её отношение к бенефитам, которые эта абстракция несёт, важно. Наши примеры (std::array и ranged-for), наверное, можно назвать примерами zero-cost, во всяком случае в релизном рантайме. Поэтому они так показательны. Но, например, тут можно послушать про очень интересный пример о std::unique_ptr и о том, как он не бесплатен по отнешению к сырым указателям.
Если перейдёте на std::array, будет интересно потом почитать о том, что получилось. Случились ли замедления и на сколько стало/не стало удобнее.
А за что минус? Статья сделала доброе дело, хорошо жеж)
Спасибо и вам, рад, что понравилось!
Касательно того, почему он в некоторых тестах оказался быстрее, чем С массив, хотя реализован через С массив - это, вообще, интересно.
std::array является частью стандартной библиотеки начиная со стандарта С++11. Любой компилятор, следующий стандарту, должен его содержать.
Из ассемблерного кода видно, что, действительно, в оптимизированной сборке на месте вызова operator[] стоит расчёт индекса и доступ к элементу, то есть код идентичнен коду для С масисва. Мне кажется, вам придётся показать, что в релизных сборках такого встраивания может не быть для того, чтобы показать не эквивалентность примеров.
Отпишу сначала про предсказатель, потом про косвенность в следующем комментарии.
Касательно подобных железных вещей практической экспертизой я похвастать не могу, конечно. Но. Если правильно понимаю, современные архитектуры не поддерживают инструкции, напрямую влияющие на предсказатель, в этом вы безоговорочно правы. Так же вы безоговорочно правы и касательно генерации кода - использование указанной интриники может привести к реорганизации кода. При этой реорганизации, например, инструкции двух ветвей условного оператора могут быть поменяны местами. Эта перестановка, в свою очередь, может повлиять на то, какую ветвь исполнения предсказатель выберет за наиболее вероятную.
Вы согласитесь с подобным описанием?
Ну да, чаще всего - это обёртка над С массивом.
Хорошее замечание! "Exception specification" проверяется в конце personality routine (обычно), ровно так же, как и сам брошенный эксепшн, то есть через type_info.
А noexcept также оптимизирует код, так как убирает lsda из функции, вызывающей noexcept функцию. Вот тут дали ссылку на обалденный доклад, в котором говорится, что это прирост к перформансу не слишком большой, правда.
Ну кстати да. Тут тоже выходит указатель на массив указателей. Спасибо!
Это был риторический вопрос, но спасибо)
"When you are a compiler author, you can make things up".