Little 3D engine SDL2 + x64 + AVX support (NASM)

Utilisateur anonyme - 1 oct. 2014 à 20:02
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019 - 7 oct. 2014 à 13:39
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/100763-little-3d-engine-sdl2-x64-avx-support-nasm

BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
7 oct. 2014 à 13:39
je viens de te mettre un message privé sur ce site, ton mail semble invalide.
Utilisateur anonyme
7 oct. 2014 à 12:41
^^
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
7 oct. 2014 à 12:07
bon alors toujours pas de mails d'alerte réponse, ça me burne car obligé de vérif ici si réponse, pas optimal pour concentration sur mon taf.

Comme ton sujet m'intéresse, on peut continuer par mail si tu veux.

monPseudoEnMinuscule AT outlook Point COM
C'est vrai que c'est mieux de faire de l'asm inline ou pur asm, que des fonction intrinsics avec leur prolog, j'en suis pas fan.

Mais bon pour l'asm inline, j'ai un problème, c'est la lenteur de leur exécution, je sais pas pourquoi mais lorsque j'ai implémenté ma fonction rotate_matrix en inline, je suis descendu de -100 fps, bizarre :/

je sais pas si ça peut aidé, mais j'ai activé le parallélisme, enfin toutes les optimisations "possible" sur icl.
D'ailleurs je sais pas comment le compilateur peut paralléliser un programme oO
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
7 oct. 2014 à 09:40
Je n'utilise quasi jamais d'intrinsics pour calculs lourds.

Exemple prog de comparaison avec 2 boutons:

typedef struct _BNDT {
float (*pfunc) (float);
HWND hedT; // pour ticks resultants
HWND hlb; // listbox affichage resultats
} BNDT, *PBNDT;

dialogProc:
msgINITDIALOG:
...
bdt[0].hedT = GetDlgItem(hdlg, IDED_A);
bdt[1].hedT = GetDlgItem(hdlg, IDED_B);
bdt[0].hlb = GetDlgItem(hdlg, IDLB_A);
bdt[1].hlb = GetDlgItem(hdlg, IDLB_B);
bdt[0].pfunc = cosf;
bdt[1].pfunc = bnCosF;
return 1;
msgCOMMAND:
dwprm = (DWORD) wParam;
if(dwprm == IDCANCEL) goto dlgCLOSE;
if(dwprm < IDBT_A) goto zeroRET;
if(dwprm > IDBT_B) goto zeroRET;
tstACOSF(dwprm - IDBT_A);
return 0;
dlgCLOSE:
EndDialog(hdlg, 0);
return 0;


void tstCOSF(DWORD idx)
{
BYTE buf[56];
float flts[396], f;
UINT64 deb, fin;
int i;
PBNDT pdt = &bdt[idx];

SendMessage(pdt->hlb, LB_RESETCONTENT, 0, 0);
SendMessage(pdt->hlb, WM_SETREDRAW, 0, 0);

remplir396Flts(flts);

deb = __rdtsc();
for(i = 0; i < 396; i++) flts[i] = pdt->pfunc(flts[i]);
fin = __rdtsc();
fin -= deb;
*bnuqwtoa(fin, buf) = 0;
SetWindowText(pdt->hedT, buf);

// AFFICHAGE PERSO DANS LISBOX CORRESPONDANT AU BOUTON
buf[8] = 32;
for(i = 0; i < 396; i++) {
cDwToFullHex(*((DWORD*) &flts[i]), buf);
*bnFtoa(flts[i], buf + 9) = 0;
SendMessage(pdt->hlb, LB_ADDSTRING, 0, (LPARAM) buf);
}
SendMessage(pdt->hlb, WM_SETREDRAW, 1, 0);
SendMessage(pdt->hlb, LB_SETCURSEL, 0, 0);
}
Utilisateur anonyme
7 oct. 2014 à 02:48
De retour, alors voilà, j'ai fait un nouveaux test de vitesse, je t'invite a lire mon topic ici:
https://software.intel.com/en-us/forums/topic/530519?page=2#comment-1800623

Bon alors voilà, je sais plus quoi pensé :/
Utilisateur anonyme
5 oct. 2014 à 21:16
ok, je verrais ça.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
5 oct. 2014 à 14:23
NON, on n'abandonne pas ni on ne tire de conclusions au 1er échec.

Insiste, je te promets qu'on peut mettre de 15 à 20 % dans la vue aux fonctions des compilos, tests faits avec celles de VS et ICC à chaque modif. Les fonctions intrinsèques à la FPU sont à classer au musée du siècle dernier, leur lenteur est affligeante.
Utilisateur anonyme
5 oct. 2014 à 10:17
Mais en effet, les fonction trigo sont trés lourde a calculer, en supprimant ce calcule, je gagne 35-40 fps
Utilisateur anonyme
5 oct. 2014 à 10:04
J'ai intégrer ce code, et malheureusement je me retrouve avec 20 fps en moins :/
Donc je garde la technologie FPU ^^.
C'est bon j'ai compris pourquoi intel n'appelle pas fsincos, dans optimization reference manual (intel doc), fsincos à 281 de latence alors que les instructions citée dans le code désassemblé, valent 2 à 6, par contre pour les antiques instruction: sub, and, cmp, j'ai pas vu.

ce code source de la fonction intrinsincs: sincos_ps_asm() ressemblant un peu au code decompilé:

code: https://github.com/mario007/renmas/blob/master/renmas3/asm/sincosps.py

Faut vraiment que je mette a jour sur les extensions ISA ^^
Utilisateur anonyme
5 oct. 2014 à 05:30
je n'ai pas cherché a comprendre comment il fait (flemme), mais c'est bel et bien la fonction trigo, si je n'ai pas fait d'erreur de traçage :/
C'est bon, j'ai réussi a dessasemblé la fameuse fonction trigo utlra rapide:
( __libm_sse2_sincos) (grace a http://x64dbg.com trés bon débogueur )



sub rsp, 68
movaps ss:[rsp+0x40], xmm7
movaps ss:[rsp+0x30], xmm6
movsd ss:[rsp+0x70], xmm0
pextrw eax, xmm0, 3
and ax, 0x7FFF
sub ax, 0x3030
cmp ax, 0x10C5
ja libmmd.1800FDC1F
;{
unpcklpd xmm0, xmm0
movapd xmm1, ds:[0x18020EB70]
mulpd xmm1, xmm0
movapd xmm2, ds:[0x18020EB60]
cvtsd2si edx, xmm1
addpd xmm1, xmm2
movapd xmm3, ds:[0x18020EB50]
subpd xmm1, xmm2
movapd xmm2, ds:[0x18020EB40]
mulpd xmm3, xmm1
add rdx, 0x1C7600
movapd xmm4, xmm0
and rdx, 0x3F
movapd xmm5, ds:[0x18020EB30]
lea rax, qword ds:[0x18020D9E0]
shl rdx, 6
add rax, rdx
mulpd xmm2, xmm1
subpd xmm0, xmm3
mulpd xmm1, ds:[0x18020EB20]
subpd xmm4, xmm3
movapd xmm7, ds:[rax+0x10]
movapd xmm3, xmm4
subpd xmm4, xmm2
mulpd xmm5, xmm0
subpd xmm0, xmm2
movapd xmm6, ds:[0x18020EB10]
mulpd xmm7, xmm4
subpd xmm3, xmm4
mulpd xmm5, xmm0
mulpd xmm0, xmm0
subpd xmm3, xmm2
movapd xmm2, ds:[rax]
subpd xmm1, xmm3
movapd xmm3, ds:[rax+0x30]
addpd xmm2, xmm3
subpd xmm7, xmm2
mulpd xmm1, xmm7
movapd xmm7, ds:[rax+0x10]
mulpd xmm2, xmm4
mulpd xmm6, xmm0
mulpd xmm3, xmm4
mulpd xmm2, xmm0
mulpd xmm7, xmm0
mulpd xmm0, xmm0
addpd xmm5, ds:[0x18020EB00]
mulpd xmm4, ds:[rax]
addpd xmm6, ds:[0x18020EAF0]
mulpd xmm5, xmm0
movapd xmm0, xmm3
addpd xmm3, ds:[rax+0x10]
addpd xmm6, xmm5
movq xmm5, xmm6
unpckhpd xmm6, xmm6
unpcklpd xmm5, xmm5
mulpd xmm6, xmm7
mulpd xmm2, xmm5
movapd xmm7, xmm4
addpd xmm4, xmm3
movapd xmm5, ds:[rax+0x10]
subpd xmm5, xmm3
subpd xmm3, xmm4
addpd xmm1, ds:[rax+0x20]
addpd xmm5, xmm0
addpd xmm3, xmm7
addpd xmm1, xmm5
addpd xmm1, xmm3
addpd xmm1, xmm2
addpd xmm1, xmm6
addpd xmm1, xmm4
movq xmm0, xmm1
unpckhpd xmm1, xmm1
;} jmp libmmd.1800FDE1E
; ... Prépare les donnée a etre traitée, a mon avis.
libmmd.1800FDC1F:
; ... Contient autant d'instruction SIMD que celles du 1st bloc.
ret


J'ai envie de placer un no-comment, mais bon c'est made by intel donc je reste perplexe.
Non je n'ai que SDL2.dll dans le dossier où est l'exe, et je doute que SDL2 posede une telle fonction ^^.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
4 oct. 2014 à 17:58
Verifie que tu ne lies pas staztiquement ton exe à une DLL.
Quand tu seras sans aucune dépendance alors le code sera dans l'exe par force.
Utilisateur anonyme
4 oct. 2014 à 17:49
Cette fonction provient de intel MKL, et pas de code source disponible :/
J'ai a peu prés les même option, j'utilise vs2013.
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
4 oct. 2014 à 10:02
Je ne reçois pas de mail pour le suivi de cette discussion, dur dur...

Avec ICC, je compile fichier C ainsi depuis un build.bat :
@set optCL=/Gs9999999 /c /nologo /Ox /QxSSE4.2 /EHc /Qftz- /wd266 /Gy /WX- /MP /Qsafeseh- /W3 /GF /GS- /GR- /TC /D WIN32 /D NDEBUG /D _WINDOWS /D _MBCS /Fo"%dirOUT%\"
@%dirINTL%icl.exe %optCL% %DirProj%%NAME%.c
Utilisateur anonyme
3 oct. 2014 à 21:40
Bon ce probleme je le me a l'ecart, je suis en train de porter le code pour degager la SDL pour la WinAPi.

Merci
J'ai déja porter mon code en c, mais:
call __libm_sse2_sincos (intel compiler)

Et il appel cette fonction a chaque appel de fonction sin() ou cos().

Etrange ..., sois il utilise une instruction non repertorié ou sois il le calcul manuellement .
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
3 oct. 2014 à 21:06
En open source, je n'ai jamais vu de fonctions trigo SIMD mais sait-on jamais... J'avoue ne pas être très doué pour les investigations sur le net.

Comme je fais dans les calculateurs, il est clair que j'ai mes biblis que je fais évoluer en suivant sortie des CPUs Intel. Pour l'instant elles sont au niveau SSE 4.2, je trouve que AVX2 n'apporte riien de significatif pour les calculs trigo.

UNE RUSE:
tu compiles un mini prog en C appelant sin(). En extraire le code sin() par décompilation ne devrait poser aucun probleme, idem pour les autres fonctions trigo. Fais en sorte de compiler avec ICC si possible car on peut lui indiquer le niveau SIMD voulu. Avec VS il faut placer "int __isa_available = 2;" avant les fonctions.
Cela fait, ne te restera qu'à virer les traitements d'erreur (errno et autres antiquites). Pour info, je retourne 0 quand expn du float est fullBits1 et basta.

Bon taf.
connaissais pas cette instru, merci, il n'existe pas de fonction sin et cos version SIMD ou AVX :/ en tout cas pas sur gladir
BruNews Messages postés 21040 Date d'inscription jeudi 23 janvier 2003 Statut Modérateur Dernière intervention 21 août 2019
3 oct. 2014 à 18:12
Salut,

ROUNDPS xmm0, xmm1/mem128, imm8
Arrondir, tronquer, ...

Tant que tu auras les calculs trigo en FPU, adieu vitesse.

Bonne continuation.
Utilisateur anonyme
3 oct. 2014 à 16:47
Qu'est-ce qui est meilleur ?
je pense que c'est le meilleur
Rejoignez-nous