- 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
- 70
- 71
- 72
- 73
- 74
void sort8(uint64_t a[8])
{
uint64_t a0;
uint64_t a1;
uint64_t a2;
uint64_t a3;
uint64_t a4;
uint64_t a5;
uint64_t a6;
uint64_t a7;
SORT2(a[0], a[1], a0, a1);
SORT2(a[2], a[3], a2, a3);
SORT2(a[4], a[5], a4, a5);
SORT2(a[6], a[7], a6, a7);
uint64_t a_tmp[8];
MERGE_2_4(a0, a1, a2, a3, a_tmp[0], a_tmp[1], a_tmp[2], a_tmp[3]);
MERGE_2_4(a4, a5, a6, a7, a_tmp[4], a_tmp[5], a_tmp[6], a_tmp[7]);
uint64_t *ptra1 = &a_tmp[0];
uint64_t *ptra2 = &a_tmp[4];
for (size_t i = 0; i < 4; i++)
{
if (*ptra1 < *ptra2)
{
a[i] = *ptra1;
ptra1++;
}
else
{
a[i] = *ptra2;
ptra2++;
}
}
for (size_t i = 4; i < 8; i++)
{
if (ptra1 == &a_tmp[4])
{
while (ptra2 != &a_tmp[8])
{
a[i++] = *ptra2;
ptra2++;
}
break;
}
if (ptra2 == &a_tmp[8])
{
while (ptra1 != &a_tmp[4])
{
a[i++] = *ptra1;
ptra1++;
}
break;
}
if (*ptra1 < *ptra2)
{
a[i] = *ptra1;
ptra1++;
}
else
{
a[i] = *ptra2;
ptra2++;
}
}
}
Мерж сорт, специализированный на 8 элементов. Вот доказательство корректности https://paste.debian.net/hidden/cce6d31a/
Эта херня по итогам уделывает в скорости std::sort, если им сортировать куски по 8 элементов.
А, внутри if'а. Сорре.
Кто-нибудь сможет быстрее сортировку на восемь uint64_t сделать (можно даже попробовать какое-нибудь SSE, если оно чем-то сможет помочь)? std::sort отстает от этого кода на GCC.
Подстраховался от эсэсёбства? :)
Если последнюю стадию улучшить (наанроллить) в моем варианте, можно быстрей перфоманс сделать.
Да, если с PGO оптимизировать обычный std::sort, он оба варианта уделывает по пирфомансу
https://paste.debian.net/hidden/eadc947e/ - вот код для тестов, если интересно
Теперь std::sort опять проигрывает, даже с PGO. Видимо этот std::sort по дизайну так запилен, чтоб частично сортированнные массивы досортировывать (досортировывать массивы из одних нулей - легко!), а если еще PGO использовать, то тогда вообще супер быстро получается.
https://paste.debian.net/hidden/368b30a7/
https://paste.debian.net/hidden/d6c6cd71/ тестовый код
Вывод времени
time = 154968303
time = 149922928
time = 151220900
time = 150623575
Для GCC-8 всё сильно медленней:
time = 381412656
time = 381636722
time = 381310683
time = 379839114
(тогда можно будет увидеть саму функцию в ненаанролленом виде).
И что же мы видим в случае clang?
куча сравнений и условных мувов.
Что же касается GCC:
Мы видим кучу меток и условных переходов, тут явно какой-то косяк компилятора. Надо будет в багзиллу GCC ченить накатать по этому поводу.
sssssssssse3
Кстати можно на stm'ке с NEONом попробовать.
http://www.greenarraychips.com/home/documents/greg/PB001-100503-GA144-1-10.pdf
... можно срать в два унитаза в сорок тысяч раз быстрей.
С 256-битными интринсиками получилось вроде красиво (каждый сортирующий слой из cmpgt + blend + blend и между ними небольшие перестановки по 1-2 инструкции), но почему-то на треть медленнее невекторизованной битонки. Неужели AVX такой тормозной?
oa = a < b ? a : b;
ob = a < b ? b : a;
Серьёзно, производители кококонпеляторов знают про «SSE» и «AVX», но игнорируют «CMOV»?
Хотя с другой стороны, в 32- и 64-битном режимах с появлением s-i-b (scale-index-base) она и вправду стала не нужна.
То ли дело «PDP-11», у которого любую инструкцию можно было использовать с любым набором регистров (было всего несколько исключений для спецрегистров).
Даже «ARM» кококококонсистентнее, потому что у него предикаты есть у всех инструкций, а не только у «CMOV».
Погуглил... Я проспал появление «Моста Песочка» и «Ускоренной единицы обработки».
6800 и 68000.
Были серии с укороченным названием T34, Т36, Т37 (вместо длинных КР580, К1810).
Были микропроцессоры с буквами ВП, ВЕ, ИК, ХЛ вместо ВМ.
У «Эльбрусов» и сейчас такие наименования: 1891ВМ10Я, 1891ВМ11Я.
Да почти у всех чипов ебанистические названия, на самом деле. Тут скорее пекашные процы - исключение.
• Операционная система: OS/2.
• Интерпретатор скриптов: PL/1.
• Система управления базами данных: DB/2.
PL/0 есть. Вообще у PL/1 много диалектов.
Programming Language for Division by Zero?
http://govnokod.ru/24481#comment420978
http://govnokod.xyz/_24481/#comment-376917
>> In the third and last edition of his book on compiler construction, Wirth replaced PL/0 with Oberon-0.
Интересно, существовала ли Модула-0 или Ада-0.
Ох, а то я уж подумал, что на таком настоящие программы писали.
Современные школьники наверно уже и языки без замыканий считают говном.
Слишком очевидно, что это одно и то же, названное разными словами. Аргумент - это фактический параметр.
Тонкости нужны только в лямбда-исчислении и при построении трансляторов.
А это уже сомнительная фича.
Ну то есть хорошо бы два режима - "скалярный", когда она включена и "векторный", когда выключена, по умолчанию - "векторный"
(Это я исходя из опыта работы с JS, где можно в переменной хранить сначала число, потом - после усложнения логики программы - массив или объект, что вызовет глюки, если "скалярный" режим работает по умолчанию)
https://wandbox.org/permlink/IxOATTwP2gBcbNwE
А ещё есть прикольный «std::tie()», но он ебанутый.
То ли дело EP4CE22F17C6N.
А что там помнить? LUT'ы, регистры, умножители, память, PLL'ки, I/O блоки. Она по структуре проще многих контроллеров, на самом деле.
Это ж не проц... Напишешь - будут (если влезут, конечно).
То ли дело SoftICE (RIP)
https://godbolt.org/z/yLGWmR - использована опция "-x c" - если ее убрать, cmov-ы пропадут. Поэтому я за Си.
на случайных данных будет оччень малая вероятность, что на первом же 64-битном куске оба числа будут одинаковы (если быть точным, вероятность эта равна 1/18446744073709551616 - вероятность случайно угадать 64-битное число)
а процедура обмена двух uint1024_t уже будет достаточно дорогой. Но можно не менять сами uint1024_t, а хранить некий вспомогательный массив индексов
А потом уже в конце можно пораспихивать все эти массивчики через этот говномассив с перестановками, но если мы сортируем большой массив (а не кусочками по 8 штук) то у нас от прыганья по этим индексам будет промахи кэша, в общем тут много чего можно понапридумывать с этим говном