во втором случае выше вероятность что компилятор сделает всё без перехода
А, то есть нужно конкретно избегать if else ветвлений, а не сравнений?
смысл в том чтобы избежать команд перехода в результирующем асме, некоторые компиляторы и так сделают что нужно
Я как слышал jump и у ему все подобные практически бесплатны, нет?
проблема в ветвлении, ветвление требует предугадать место прыжка
Смешные у тебя шутки, проблема именно в переходе, сам кмп выполняется быстро - обычное вычитание и выставление флагов без записи результата куда-либо, однако в любом современном (да и 20-летней давности) процессоре реализована конвейерная обработка команд, таким образом у тебя команды обрабатываются параллельно, таким образом пропускная способность конвейера обратно пропорциональна времени обработки команды на одном участке конвейера, в свою очередь общее время исполнения команды существенно больше и называется латентностью конвейера и равняется времени прохождению всех этапов обработки команды с начала до конца конвейера, таким образом процессору надо знать, какую команду загружать следующей, чтобы конвейер был всегда заполнен и была высокая пропускная способность, а в случае перехода процессору надо угадывать - на какую инструкцию будет выполнен переход (для этого зачастую используют двух битовое значение в котором фиксируют результаты предыдущих переходов, хотя мб что-то могло уже и поменяться), таким образом, если процессор не угадал, то мы получаем пенальти на половину конвейера (половину т.к. примерно к середине конвейера становится известен результат сравнения и он может быть передан сразу для загрузки следующей инструкции), а т.к. на современных процессорах конвейер точно содержит более 20 ступеней, то задержка получается довольно существенной.
@disba1ancer я ни в чём не ошибся?
Задаюсь вопросом тогда что лучше) https://godbolt.org/z/czKqY83PY
Так нет однозначного ответа, от архитектуры и компилятора зависит, а вообще лучше сделать вставку под x86 и обернуть макросами, чем хардкодить размер инта (хотя и можно было взять (CHAR_BIT * sizeof a - 1)), тем не менее нет никаких гарантий, что под условный IA64 твоя программа будет работать эффективнее классической реализации. Если интересно, можешь ручками посчитать примерно - смотришь сколько исполняются твои инструкции в тактах, добавляешь половину латентности, хотя прям точного результата не получишь.
я всех деталей точно не знаю, но выглядит, как нормальное объяснение
Там всё равно SIMD будет в обоих случаях, ну какие бранчи?
Так вроде бранчи не позволяют его использовать
Наоборот, такое очень хорошо векторизуется, и компиляторы достаточно умные, чтобы убрать if. Вот gcc выдаёт в теле цикла для обоих вариантов одно и то же, элементы инты, в xmm2 продублировано по всем элементам 49. После цикла горизонтальное суммирование ещё. Из бранчей только сам цикл: movdqu xmm0, XMMWORD PTR [eax] movdqu xmm3, XMMWORD PTR [eax] add eax, 16 pcmpgtd xmm0, xmm2 pandn xmm0, xmm3 paddd xmm1, xmm0
Ну получается не нужно избегать if else если это можно математическим путем решить?
Обсуждают сегодня