0 1
Ма ти не знаеш ли? Вече е срамно да се пише на асемблер. Гледат с лошо око, колегите.
Хм, моите колеги, като че ли не ме гледат с лошо око. Добре, че не са програмисти.
И като видиш как С пише по-оптимално от тебе...
хубаво е все пак да имаш job security, затова колкото повече асемблер, толкова по-добре
Кой ви учи на тез глупости ве, банкирането ми е мацано на .нет, кажи неко асемблерска банка, че по-сигурна 🤪 🤓 🤑 🙃 ...
Оп, сори, после разбрах ко искаше да кажеш. Дремя на едни лекции по многозадачност. Съгласен съм.
Абе BIGBUGEX, какво ще стане ако края на вектора е в невалидна памет? Ще гръмне ли програмата или AVX2 знае как да го оправи? Защото не го виждам в кода ти.
Ето моята SVE имплементация, базирана на оптимизирана версия на strchr. Тества за нула.
setffr /* initialize FFR */
ptrue p1.b /* all ones; loop invariant */
mov x1, xzr
dup z1.b, 'p' /* replicate byte across vector */
dup z2.b, 's' /* replicate byte across vector */
.p2align 4
0: ldff1b z0.b, p1/z, [x0, xzr]
rdffrs p0.b, p1/z
b.nlast 1f
/* First fault did not fail: the whole vector is valid.
Avoid depending on the contents of FFR beyond the branch. */
incb x0 /* speculate increment */
cmpeq p3.b, p1/z, z0.b, 0 /* search for 0 */
b.ne 1f
/* no end string */
brka p4.b, p1/z, p3.b /* find first 0 */
cmpeq p2.b, p4/z, z0.b, z1.b /* search for 'p' */
decp x1, p2.b /* count the predicates and subtract them from x1 */
cmpeq p3.b, p4/z, z0.b, z2.b /* search for 's' */
incp x1, p3.b /* count the predicates and add them to x1 */
b 0b
1: /* end string or first fault */
brka p4.b, p0/z, p3.b /* find first 0 */
cmpeq p2.b, p4/z, z0.b, z1.b /* search for 'p' */
decp x1, p2.b /* count the predicates and subtract them from x1 */
cmpeq p3.b, p4/z, z0.b, z2.b /* search for 's' */
incp x1, p3.b /* count the predicates and add them to x1 */
mov x0, x1
ret
Скоростта на Graviton4 e 1.86 пъти по-бавна от eqsub.
Ето и версията ми за SME. Това е реално Streaming SVE, но имплементацията е различна защото SSVE няма FFR и incp/decp са много бавни (мързи ме да обяснявам, но ако някой е любопитен може да го направя).
smstart
dup z1.b, 'p' /* replicate byte across vector */
dup z2.b, 's' /* replicate byte across vector */
dup z3.b, 0 /* all 0s for sel */
dup z4.b, 1 /* all 1s for sel */
dup z5.b, -1 /* all -1s for sel */
dup z8.s, 0 /* return value(s) */
ptrue p1.b /* all ones; loop invariant */
.p2align 4
0: ld1b z0.b, p1/z, [x0] /* read bytes in vector */
incb x0 /* speculate increment */
dup z9.h, 0 /* 32-bit count for the iteration */
cmpeq p3.b, p1/z, z0.b, 0 /* search for 0 */
b.ne 1f
/* no end of string */
cmpeq p2.b, p1/z, z0.b, z1.b /* search for 'p' */
sel z10.b, p2, z5.b, z3.b /* for each match, select -1s from z5 */
cmpeq p3.b, p1/z, z0.b, z2.b /* search for 's' */
sel z10.b, p3, z4.b, z10.b /* for each match, select 1s from z4 */
sadalp z9.h, p1/m, z10.b /* widen to 16 bit by adding pairwise elements*/
sadalp z8.s, p1/m, z9.h /* add to the total count, widening to 32 bit */
b 0b
/* end of string */
1: brka p4.b, p1/z, p3.b /* find first 0 */
cmpeq p2.b, p4/z, z0.b, z1.b /* search for 'p' */
sel z10.b, p2, z5.b, z3.b /* for each match, select -1s from z5 */
cmpeq p3.b, p4/z, z0.b, z2.b /* search for 's' */
sel z10.b, p3, z4.b, z10.b /* for each match, select 1s from z4 */
sadalp z9.h, p1/m, z10.b /* widen to 16 bit by adding pairwise elements*/
sadalp z8.s, p1/m, z9.h /* add to the total count, widening to 32 bit */
saddv d0, p1, z8.s /* reduce counts to scalar register */
fmov x0, d0
smstop
ret
Скоростта е десетки пъти по-бавна от eqsub на Apple M4. Явно SME не е много подходящ за такива дребни алгоритми.
Няма да гръмне. Подравнявам старта на 32 байта и със съответните битове за валидност инвалидирам операциите които са пред масива. От там на сетне обработвам адреси кратни на 32 байта. Ако изскочи '\0' в текущия пакет от данни се излиза от цикъла като се инвалидират бройките след него.
Много добре е това. Ще го разгледам кода въпреки че не вдявам много.
Може да няма лесен начин за тестване за 0 на SME. Също така е трудно без участието на генерални регистри да се инвалидират 'p' и 's' бройките идващи непосредствено след нулевия знак.
А, това с подравняването в началото е хитро, не се бях сетил. Ще помисля дали/как мога да го направя за SVE/SME. SME е 512 битови вектори, така че ще чете направо цяла cache line наведнъж.
Друго нещо, което трябва да пробвам е четенето наведнъж на 4 вектора (LD4x). Ще чете 256 байта за една инструкция. Не че е задължително да е по-бързо, но ще видим.
0 1