TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.36K subscribers
Post #1082 3.4K
Loop unrolling. Мануально
#опытным

Мы можем конечно и сами разворачивать циклы, но код будет повторяться и от этого потенциально много проблем будет.

Ну хорошо, у нас есть все инструменты, чтобы явно не повторять код. Например вот так:

template <typename F, std::size_t... Is>
void repeat_unrolled_impl(F&& f, std::index_sequence<Is...>)
{
((f(), void(Is)), ...);
}

template <std::size_t Iterations, typename F>
void repeat_unrolled(F&& f)
{
repeat_unrolled_impl(std::forward<F>(f),
std::make_index_sequence<Iterations>{});
}

volatile int i = 0;

int main()
{
repeat_unrolled<6>([&]{ ++i; });
}


Определяем парочку шаблонных функций, которые с помощью std::index_sequence и fold expression полностью изничтожают цикл и просто подряд вызывают функтор столько раз, сколько вы указали в шаблонном параметре repeat_unrolled.

Асм можете посмотреть тут. Здесь конечно есть одна хитрость с volatile, чтобы компилятор не соптимизировал наши тривиальные вычисления, но тем не менее.

Хотите частичную развертку? Да пожалуйста:

template <typename F, std::size_t... Offsets>
void call_with_offsets(F&& f, std::index_sequence<Offsets...>) {
((f(), void(Offsets)), ...);
}

template <std::size_t Iterations, std::size_t UnrollFactor, typename F>
void partial_unroll(F&& f) {
constexpr std::size_t full_blocks = Iterations / UnrollFactor;
constexpr std::size_t remainder = Iterations % UnrollFactor;

for (std::size_t block = 0; block < full_blocks; ++block) {
call_with_offsets(std::forward<F>(f),
std::make_index_sequence<UnrollFactor>{});
}

for (std::size_t i = 0; i < remainder; ++i) {
f();
}
}

volatile int counter = 0;

int main() {
partial_unroll<101, 4>([&]{ ++counter; });
}


Приемы используются те же, развертку тоже можете сами увидеть.

Зачем этот пост? Да просто наткнулся на такой код при подготовке к этой серии статей. Удивился, что в нескольких источниках упоминается такой способ и решил поделиться. Не знаю на счет применимости такого кода, выглядит сомнительно и не во всех ситуациях подойдет.

Но по крайней мере где-нибудь на собеседовании можно задать такую задачку на шаблоны. И прикладной смысл понятен и не особо сложно как будто бы.

Use templates in the right place. Stay cool.

#template #interview
  • ❤ 16
  • 👍 7
  • 🔥 5
  • 🤯 2
More from @grokaemcpp
  1. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  2. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  3. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  4. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  5. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
  6. Sep 25, 2026​​std::spanstream #опытным Радостная весть для всех, кто пользуется iostreams! В C++23 доб…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →