Mémoire dans un tableau dynamique

JnBiz Messages postés 18 Date d'inscription mardi 18 avril 2006 Statut Membre Dernière intervention 30 mai 2006 - 16 mai 2006 à 19:08
JnBiz Messages postés 18 Date d'inscription mardi 18 avril 2006 Statut Membre Dernière intervention 30 mai 2006 - 17 mai 2006 à 17:46
Bonjour,
Dans l'unité TMatrix que je développe, les matrices sont formées par des tableaux dynamique de type extended (10 octets).
Pour optimiser certaines routines je compte mettre un peu d'assembleur. Or je rencontre un réel problème d'accés en mémoire, en effet les données du tableaux dynamiques ne sont pas toujours placées là ou on les attend.
En fait on s'attendrait à ce que les données du début de la ligne n+1 soient placées juste après la fin de la ligne n. La plupart du temps c'est le cas (avec un saut de 128 bits entre chaques lignes), mais à certain moment cela ne marche pas.

Exemple: J'ai transformé une fonction qui marche parfaitement pour des variables statique, pour des variables dynamiques j'obient ceci: (j'ai juste rajouté le saut de 128 bits)
Les données sont ici de type double (64 bits)

function FastMul(M1,M2:TMatrix):TMatrix;
var i,q,c,n,RC,RCB,RC2:integer;
s:double;
pX,pY,pZ:pointer;
begin
RC:=M1.RowCount;
RC2:=RC+3; // le +3 est du au décalage de 128 bits+le saut de la colonne 0 (64 bits)
RCB:=(RC+3)*8;
n:=RC;
RESULT:=Zeros(RC,RC); //on met à zero la matrice
pX:=@M1.Cells[1,0]; //les premières données sont écrites à la colonne n° 1 => saut de 64 bits
pY:=@M2.Cells[1,0];
pZ:=@RESULT.Cells[1,0];
c:=0;
for i:=1 to n do begin
q:=(i-1)*(RC+3);
asm
push esi
push edi
push edx
push ecx
push ebx
push eax

mov edi,pY //edi=pY+(k-1)*RC+j-1
mov esi,q
shl esi,3
add esi,pZ //esi=pZ+(i-1)*RC+j-1

finit
mov edx,0
@b2: //for edx:=1 to n do begin
mov ecx,i
sub ecx,1
imul ecx,RC2
add ecx,edx
shl ecx,3
add ecx,pX
add ecx,8
fld qword [ecx]
fst s //M1[i,k]
mov ecx,n
@b3: //for ecx:=n to downto 0 do begin
prefetch [edi+ecx*8-256] //fait gagner 40% !
fld qword [edi+ecx*8] //M2[k,j];
fmul st(0),st(1)
fld qword [esi+ecx*8]
faddp
fstp qword [esi+ecx*8] //M[i,j]:=M[i,j]+s*M2[k,j];
loopnz @b3
ffree st(0)
add edi,RCB //même saut de 128+64 bits
inc edx
cmp edx,n
jne @b2
pop eax
pop ebx
pop ecx
pop edx
pop edi
pop esi
fninit
end;
end;
end;

Après quelques tests, on constate que cette méthode fonctionne de manière totalement aléatoire (fonctionne 10 fois, puis bug etc).
Lors du déboguage, on constate que certaines lignes des matrices ne sont pas au bon endroit.
Voila, si vous pouvez m'aider, merci d'avance.

5 réponses

DeltaFX Messages postés 449 Date d'inscription lundi 19 avril 2004 Statut Membre Dernière intervention 8 avril 2009 2
16 mai 2006 à 20:53
Je crois que c'est indémer...able. Si je ne m'abuse, c'est zindoz qui s'occupe du bigntz, et pour faire court, ca fragmente en Ram. Et la,  pour les sauts ahem,....

J'en connais pas assez en delphi, mais a priori il existe des composants plus adapté, genre TobjetList, Tcontnr... que l'on doit pouvoir packer avant manip asm.

Ou alors, si tu veux de l'asm, de la meme manière qu'on évitera en graphisme avancé d'utiliser du 24 bit (format batard, quelle idée d'avoir 3 octets, c'est chiant 3, comme puissance de 2....), de la meme manière que dans certain cas de Simul Num ( sur machines parralleles) on prefere alourdir le maillage pour pouvoir basculer des bancs memoires complet, il faudra peut-être éviter le dynamique pur. 
0
JnBiz Messages postés 18 Date d'inscription mardi 18 avril 2006 Statut Membre Dernière intervention 30 mai 2006
16 mai 2006 à 22:37
Effectivement ca a l'air compliqué, je me demande quand même ce qui est contenu dans ces 128 bits mystère, peut être bien qu'il s'y trouve l'adresse de la ligne (je m'avance) car je ne vois pas trop à quoi ca peut servir d'autre, j'imagine qu'il doit y avoir un truc du genre : bloc mémoire alloué à la ligne (sur 32 bits) adresse mémoire du prochain bloc (sur 32 bits)...
En tous cas ca n'a pas l'air pratique.

Ne peut on pas alors envisager la création dynamique de tableaux statiques ? c'est peut être ce que tu sous-entends en parlant de dynamique pur. Ca me faciliterait grandement la tâche et pour l'utilisation de la mémoire c'est toujours mieux d'utiliser des variables alignées.
0
f0xi Messages postés 4205 Date d'inscription samedi 16 octobre 2004 Statut Modérateur Dernière intervention 12 mars 2022 35
17 mai 2006 à 05:33
je crois qu'en assembleur il faut compter en marche arriere :

 pX:=@M1.Cells[high(M1.Cells), High(M1.Cells[0])];
 pY:=@M2.Cells[high(M2.Cells), High(M2.Cells[0])];
 pZ:=@RESULT.Cells[high(Result.Cells), High(Result.Cells[0])];

@DeltaFX : aucun probleme pour le 24bit, il est stocké dans un 32bits. et puis en asm on manipule les bits pas les octets donc comme 24 est une puissance de 2 ... ca pose aucun probleme ...
donc par exemple :

var r,g,b : byte;
asm
     MOV EAX,{RGB};
     MOV r,AL;
     MOV g,AH;
     SHR EAX,8;
     MOV b,AH;
end;

non franchement je vois pas ou est le probleme, vus que de toute façon il n'existe pas de registre 24 bits et que dans une couleur 32 bits le dernier octet correspond a l'alpha on aurait donc :

var r,g,b,a : byte;

asm

     MOV EAX,{RGBA};

     MOV r,AL;

     MOV g,AH;

     SHR EAX,16;

     MOV b,AL;
     MOV a,AH;

end;

donc aucune difference dans la manipulation d'un octet d'une couleur 32 ou 24 bits.
0
yvessimon Messages postés 637 Date d'inscription mardi 22 avril 2003 Statut Membre Dernière intervention 9 janvier 2017
17 mai 2006 à 08:58
Alors fait une table sur une seule colonne et gérer les indice à ta façon en assembleur

[i,j] ---> [i*col+j]    ou équivalent suivant les bornes

j'ai eu le même probléme et cela fonctionne tres bien pour une matrice de 200x200
yvessimon
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
JnBiz Messages postés 18 Date d'inscription mardi 18 avril 2006 Statut Membre Dernière intervention 30 mai 2006
17 mai 2006 à 17:46
foxi, non, on compte bien "en marche avant", mais le problème n'est pas la, certaines données de tableaux dynamique ne sont pas situées juste après les dernières.
Yvessimon, je suis d'accord avec toi, seulement ce n'est vraiment pas pratique de mettre à chaque fois le i*col, d'autant que le nombre de colonnes change.
0
Rejoignez-nous