En dehors de l'erreur de syntaxe dans votre code (" "r"
->: "r"
), votre problème est paramètres dépareillées .
En regardant la sortie de S:
add rax, r8b
Depuis cnt
est size_t et bytes[i]
est un octet, c'est ce que vous attendez. Ajouter exige qu'ils soient de la même taille. Puis-je également suggérer d'utiliser des builtins au lieu de inline asm? Il évite des problèmes comme celui-ci (ainsi que beaucoup d'autres).
Est-il possible d'ajouter le résultat de POPCNT sans l'enregistrer dans un registre de premier?
Umm. C'est en fait une question entièrement différente. L'erreur que vous avez posée concerne le mélange d'un octet et d'un size_t dans une seule instruction add
. Il peut être résolu en faisant:
__asm__(
"popcnt %0, %0 \n\t"
"add %0, %1 \n\t"
: "+r" (cnt)
: "r" ((size_t)bytes[i]));
Je ne devrais pas vous encourager à continuer à ajouter de nouvelles questions (comment vais-je obtenir mes points de karma), mais en regardant ce site, le code qu'il semble jouer avec est la suivante:
uint32_t builtin_popcnt_unrolled_errata(const uint64_t* buf, int len) {
assert(len % 4 == 0);
int cnt[4];
for (int i = 0; i < 4; ++i) {
cnt[i] = 0;
}
for (int i = 0; i < len; i+=4) {
cnt[0] += __builtin_popcountll(buf[i]);
cnt[1] += __builtin_popcountll(buf[i+1]);
cnt[2] += __builtin_popcountll(buf[i+2]);
cnt[3] += __builtin_popcountll(buf[i+3]);
}
return cnt[0] + cnt[1] + cnt[2] + cnt[3];
}
Il est explicitement utilise cnt [x] pour tenter d'éviter le problème « fausse dépendance » de POPCNT.
avec gcc 6.1 et la compilation avec -m64 -O3 -march=native -mtune=native
, je vois cela comme sortie:
.L14:
popcnt r11, QWORD PTR [rcx]
add rcx, 32
add edx, r11d
popcnt r11, QWORD PTR -24[rcx]
add eax, r11d
popcnt r11, QWORD PTR -16[rcx]
add r10d, r11d
popcnt r11, QWORD PTR -8[rcx]
add r9d, r11d
cmp rcx, r8
jne .L14
qui « stocker hors dans un registre » faites-vous référence?
oublié de mentionner que j'ai commencé avec builtins mais je voulais quelque chose de plus rapide. Est-il possible d'additionner le résultat de popcnt sans le stocker dans un registre en premier? Vous avez l'idée de https://danluu.com/assembly-intrinsics/ –
merci pour la réponse? Je dois avoir été juste confondu avec ce que le blog essayait de dire. Voici vos points de karma :) –
Le blog n'a pas de date dessus, mais il a été écrit en utilisant 4.8.2. C'était il y a longtemps, donc les choses ont peut-être changé. C'est une autre raison pour laquelle je recommande d'utiliser des builtins au lieu de inline. Les builtins peuvent s'améliorer avec le temps, mais si vous écrivez en ligne, vous obtenez exactement ce que vous écrivez. BTW, si la performance est critique, l'utilisation de la popcnt 64 bits est (probablement) plus rapide que les 8 bits répétés. Vous aurez besoin de vérifier la longueur et gérer les tailles impaires, mais je voudrais l'essayer et le chronométrer. –