numbers_in.filter(x => x % 2 == 0).map(x => x / 2)
R>>Ну ты же жульничаешь — ты не положил числа в выходной массив. Ты предоставь законченное решение, тогда и сравним.
S>Это, кстати, от языка зависит. В некоторых языках map именно что создает новый контейнер: S>
r = [3, 4, 5, 6, 7, 8].filter {|x| x % 2 == 0}.map {|x| x/2}
S>Другое дело, что в таких языках никого не парит что за контейнер будет создан, как он будет расти и т.д., и т.п.
Ну я и имел в виду, что новый контейнер создается. В смысле, должно быть
numbers_out = numbers_in.filter(x => x % 2 == 0).map(x => x / 2)
Т.е. я нарочно опустил присваивание "numbers_out" для того чтобы результат казался чуть короче.
Про что rg45 и пишет что "сжульничал". У тебя его кстати тоже нет.
В "функциональном стиле" (т.е. с использованием std::ranges) синтаксический оверхед (тм) примерно такой же
Кстати почему-то у меня код с "transformed" и "filtered" не компилируется в таком виде как дан (говорит что нет такой буквы в C++ 20)
Я думаю если компилируемый код сделать там еще процентов 50 запросто прибавится на всяких приседаниях.
Здравствуйте, bnk, Вы писали:
S>>Это, кстати, от языка зависит. В некоторых языках map именно что создает новый контейнер: S>>
r = [3, 4, 5, 6, 7, 8].filter {|x| x % 2 == 0}.map {|x| x/2}
S>>Другое дело, что в таких языках никого не парит что за контейнер будет создан, как он будет расти и т.д., и т.п.
bnk>Ну я и имел в виду, что новый контейнер создается. В смысле, должно быть bnk>
numbers_out = numbers_in.filter(x => x % 2 == 0).map(x => x / 2)
bnk>Т.е. я нарочно опустил присваивание "numbers_out" для того чтобы результат казался чуть короче. bnk>Про что rg45 и пишет что "сжульничал". У тебя его кстати тоже нет.
Вообще-то есть, r называется.
Но чтобы быть совсем уж близко к первоисточнику, то следовало бы написать:
Здравствуйте, McQwerty, Вы писали:
MQ>Здравствуйте, Sm0ke, Вы писали:
S>>Замерил на годболте через chrono: https://godbolt.org/z/dK4jsoxG3 S>>На массиве с 90к элементов
MQ>Дополнил тест следующим вариантом (с предварительным resize и последующим erase для v_dest): MQ>
MQ> {
MQ> v_dest.clear();
MQ> v_dest. resize (v_src. size ()); // 1
MQ> const some_time v_start = std::chrono::system_clock::now(); // 2
MQ> my_container::iterator d = v_dest. begin ();
MQ> for (auto x : v_src)
MQ> {
MQ> * d = x >> 1;
MQ> d += x & 1 ^ 1;
MQ> }
MQ> v_dest. erase (d, v_dest. end ());
MQ> const some_time v_stop = std::chrono::system_clock::now();
MQ> std::cout
MQ> << "mcq: "
MQ> << std::chrono::duration_cast<std::chrono::microseconds>(v_stop - v_start)
MQ> << '\n'
MQ> ;
MQ> }
MQ>
А если всё же поменять местами строчки 1 и 2 ?
Ведь остальные способы работают изначально с пустым dst
Здравствуйте, bnk, Вы писали:
bnk>Кстати почему-то у меня код с "transformed" и "filtered" не компилируется в таком виде как дан (говорит что нет такой буквы в C++ 20)
Ты имеешь в виду вот этот код? Так это же boost, а не std. Причем древняя как мир библиотека. Ну и по ссылке видно, что копмилируется и работает.
Здравствуйте, B0FEE664, Вы писали:
BFE>Мне кажется, что подобную задачу в качестве примера я не первый раз встречаю. Все её решают почему-то через промежуточный буфер... Отсюда и вопрос.
Ну так кто-то один написал, а остальные копипастят. Та же самая история, почему во всех примерах с циклом используется постинкремент переменной цикла.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, bnk, Вы писали:
bnk>>Кстати почему-то у меня код с "transformed" и "filtered" не компилируется в таком виде как дан (говорит что нет такой буквы в C++ 20)
R>Ты имеешь в виду вот этот код? Так это же boost, а не std. Причем древняя как мир библиотека. Ну и по ссылке видно, что копмилируется и работает.
Здравствуйте, rg45, Вы писали:
R>И почему здесь так важен этот const, не объяснишь? Помимо правил хорошего стиля.
Потому, что ближе к функциональному программированию, меньше ошибок.
Вообще говоря я в последние время редко использую неконстантные локальные переменные. Неконстантные локальные переменные — это обычно переменные для ввода-вывода. Так получается, что все изменения состояний лежат в объектах, которые живут всё время от запуска до завершения программы. Либо, как уже написал, в вводе/выводе.
Здравствуйте, Pzz, Вы писали:
Pzz>В одну строчку — это для любителей. А профессионал напишет полэкрана текста, как в приведенном тобой примере. Потому, что он профессионал.
У профессионала вообще не возникает таких ситуаций, когда в массиве лежат данные, которые следует выкинут.
Здравствуйте, B0FEE664, Вы писали:
R>>И почему здесь так важен этот const, не объяснишь? Помимо правил хорошего стиля. BFE>Потому, что ближе к функциональному программированию, меньше ошибок. BFE>Вообще говоря я в последние время редко использую неконстантные локальные переменные. Неконстантные локальные переменные — это обычно переменные для ввода-вывода. Так получается, что все изменения состояний лежат в объектах, которые живут всё время от запуска до завершения программы. Либо, как уже написал, в вводе/выводе.
Тут я с тобой полностью согласен. Но мы тут затеяли длиной меряться, а в данном конкретном случае наличие или отсутствие const на результат никак не влияет и я пошел на сделку со своей совестью и выбросил его. Целых пять букв, шутка ли. А с пробелом все шесть!
Здравствуйте, Sm0ke, Вы писали:
S>Судя по разбросу мерить скорость на винде тоже не айс :Р S>Так на чём мерить?
Как тут уже сказали, перед замером надо "прогревать" процессор. ОС выставит для него максимальную частоту и переключит твой поток на мощное ядро. Затем, один и тот же тест надо прогонять много раз, каждый раз считать время, а затем брать например, медианное значение. Но я бы не заморачивался и использовал какую-нибудь готовую либу для бенчмаркинга. В неё это всё будет уже встроено
Мне интересно почему for + div() медленнее, чем for?
Ведь казалось бы мы делаем две операции (деление и остаток) за одну инструкцию. Но видимо в std накосячили и что-то пошло не так. Или вообще что случилось?
Здравствуйте, Sm0ke, Вы писали:
S>Мне интересно почему for + div() медленнее, чем for? S>Ведь казалось бы мы делаем две операции (деление и остаток) за одну инструкцию. Но видимо в std накосячили и что-то пошло не так. Или вообще что случилось?
Здравствуйте, Sm0ke, Вы писали:
S>Мне интересно почему for + div() медленнее, чем for? S>Ведь казалось бы мы делаем две операции (деление и остаток) за одну инструкцию. Но видимо в std накосячили и что-то пошло не так. Или вообще что случилось?
Похоже что из-за отсутствия инлайна std::div (выполняется call)
Добавил mydiv и mydiv_noinline (эмуляция вызова std::div):
std::div_t mydiv(int x, int y)
{
return { x / y, x % y };
}
std::div_t __attribute__ ((noinline)) mydiv_noinline(int x, int y)
{
return { x / y, x % y };
}
Судя по asm смартовый оптимизатор выполняет idiv — та самая одна инструкция (частное в rax, остаток в rdx), а при инлайне mydiv заменяет её код на test (AND) и сдвиг (как в варианте mcq, да и в for такой же код генерится)
mydiv_noinline(int, int):
mov eax, edi
cdq
idiv esi
sal rdx, 32
or rax, rdx
ret
Здравствуйте, rg45, Вы писали:
BFE>>Мне кажется, что подобную задачу в качестве примера я не первый раз встречаю. Все её решают почему-то через промежуточный буфер... Отсюда и вопрос.
R>Ну так кто-то один написал, а остальные копипастят. Та же самая история, почему во всех примерах с циклом используется постинкремент переменной цикла.
Я всегда префиксный инкремент использую, для любых типов. Привычка. Впрочем, я сознательно себя к этому приучал в своё время
Здравствуйте, ArtDenis, Вы писали:
AD>Для плюсов — идеальный вариант, т.к. другие или корявые или сложные
Слишком простой код, нет клёвой функциональщины. Код сразу выдаёт старпёра, с которыми и смузи выпить не о чем, и на одном электросамокате не покататься.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
TB>Слишком простой код, нет клёвой функциональщины. Код сразу выдаёт старпёра, с которыми и смузи выпить не о чем, и на одном электросамокате не покататься.
Если бы плюсы позволяли удобную и понятную функциональщину, я бы предпочёл её