- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
// https://godbolt.org/z/f4s13WEWM
#include <inttypes.h>
int test(uint32_t a, uint32_t b)
{
if (a > b)
return a+b;
return a*b;
}
int test2(uint32_t a, uint32_t b)
{
return (a+b)*(a > b) | (a*b)*!(a > b);
}
int test3(uint32_t a, uint32_t b)
{
return
((a+b) & (uint32_t)(!(a > b) - 1)) |
((a*b) & (uint32_t)((a > b) - 1));
}
int test4(uint32_t a, uint32_t b)
{
const uint32_t arr[2] = {a+b, a*b};
return arr[!(a > b)];
}
/* ASM output
test:
bltu a1, a0, .LBB0_2
mul a0, a1, a0
ret
.LBB0_2:
add a0, a0, a1
ret
test2:
bltu a1, a0, .LBB1_2
mul a0, a1, a0
ret
.LBB1_2:
add a0, a0, a1
ret
test3:
bltu a1, a0, .LBB2_2
mul a0, a1, a0
ret
.LBB2_2:
add a0, a0, a1
ret
test4:
addi sp, sp, -16
add a2, a1, a0
mul a3, a1, a0
sltu a0, a1, a0
sw a2, 8(sp)
sw a3, 12(sp)
xori a0, a0, 1
slli a0, a0, 2
addi a1, sp, 8
add a0, a0, a1
lw a0, 0(a0)
addi sp, sp, 16
ret
*/
Наглядная демонстрация того, что компилятор может насрать на ваши попытки заставить его сгенерить branchless машинный код. Получилось это только в "test4"
А то вот советуют иногда https://johnfarrier.com/c-performance-checklist-for-low-latency-systems/
> Use branchless arithmetic tricks (e.g., masks, bit shifts) to remove predictable conditionals.
Хуй там.
test4 раскатало нехило, это точно лучше, чем один условный прыг? Точнее так: всегда-ли прыг это настолько плохо? Есть же спекулятивное выполнение. Или оно нужно только чтобы мельдоний делать?
Это RISC-V. "bltu" расшифровывается как "branch if less than unsigned"
>test4 раскатало нехило, это точно лучше, чем один условный прыг?
ХЗ. Зависит от процессора наверное. Если эту же срань скомпилировать через GCC 14.2 x86-64 то получается такое:
Т.е. качественный branchless с инструкцией cmovnb оно сделало в варианте test2 только. В test4 тоже branchless, но он говно.
https://wiki.sipeed.com/hardware/en/lichee/RV_Nano/1_intro.html
https://milkv.io/chips/sg2000
It still fails at the end with these messages. I tried on both Arch Linux and ubuntu 22.04 in Virtual Box. I also tried with Debian 12
оптимизация так и прёт.
Нет, не всегда. Зависит от микроархитектуры и от вероятности срабатывания условного перехода. Вот например в https://en.algorithmica.org/hpc/pipelining/branchless/#when-predication-is-beneficial пишут:
> Using predication eliminates a control hazard but introduces a data hazard. There is still a pipeline stall, but it is a cheaper one: you only need to wait for cmov to be resolved and not flush the entire pipeline in case of a mispredict.
> However, there are many situations when it is more efficient to leave branchy code as it is. This is the case when the cost of computing both branches instead of just one outweighs the penalty for the potential branch mispredictions.
Компилятору можно через какие-то говнодирективы сказать вероятность срабатывания условия, но нет такой директивы, которая бы приказывала генерить branchless код
sum = a + b
mult = a - b
return a < b ? sum : mult
то компилятор из такого не вытаскивает понимание твоих намерений?
upd. а, ты хочешь вообще от bltu отказаться. Но тем не менее, он выплюнет джамп или bltu?
компилится бранчлесс
Какой анскилл(((
https://pbs.twimg.com/media/GiSJz5zXkAA4PTj?format=jpg&name=large
А жёсткий на 160 гигов — это уже вторая половина нулевых. Возможно, оригинальный винт сдох, и где-то примерно в 2010-м его поменяли.
Но есть две проблемы:
1. Award BIOS 4.51PG не поддерживает LBA48, поэтому винт будет работать в режиме совместимости с LBA28, т. е. видно будет первые 128 гигов. Это не беда.
2. У 4.51PG есть ошибка в коде вывода объёма жёсткого на экран, из-за которой он виснет, если объём больше 8 гигов. Я накатывал патч с rom.by, чтобы он не вис.
Значит, в этой железке пропатченный BIOS?
ну там копирайт 99, видишь?
>винт будет работать в режиме совместимости с LBA28
От BIOSа требуется только добраться до первого сектора загрузочного раздела, а дальше уже операционка сама разберется. Она может иметь свой драйвер, и работать с IDE напрямую (если конечно там не DOS: он может и соснуть)
> из-за которой он виснет, если объём больше 8 гигов
какой багор)) Этого я не знал. Но может быть пропатченный, да.
Я просто как увидел настоящий BIOS и Energy Star Ally так вспомнил детсво, и заплака и принёс сюда
Согласен, да, если у операционки есть свой драйвер, она доберётся до всех секторов.
> какой багор
Представляешь, как лоханулись создатели Award BIOS? Сам БИОС поддерживает LBA28, но в коде POST при выводе на экран диагностического сообщения переменная переполняется, и на POST он виснет, если объём приближается к 8 гигам или превосходит их. На момент создания не было больших винтов, поэтому у разработчиков всё работало.
Авторы патча к килобайтам и мегабайтам добавили гигабайты и терабайты, чтобы всё выглядело красиво. Места на патч хватило.
Кстати, знаешь, чем отличается 4.51PG от 4.5G? Более старый просто отображался на память и работал, а в более новом всё зожали в зип-файл, а перед ним поместили розжималку в ОЗУ, что позволило БИОС запихать в маленькую флешку (прошивку на 128К запихали на флешку на 64К). Зачем? Зачем? В те годы флешки на 128К были дорогими?
*****
Был ещё вариант: поставить внешний по отношению к материнке контроллер ATA, например, аппаратный RAID со своим БИОСом. Тогда весь объём будет доступен даже голому ДОСу. Но как это будет отображаться в POST, я не знаю.