Tableau à deux dimensions [C] - C - Programmation
Marsh Posté le 06-12-2007 à 03:36:12
Oué, presque bon. Dans ta boucle sur j, j'itérerai jusqu'à m et non n.
Sinon plus hardcore, tu alloues ta matrice d'un bloc et tu retrouves l'indice i, j en faisant : i * m + j. Du coup tu pourras l'initialiser avec un appel à memset et surtout libérer la mémoire avec un seul free (ce qui en C, n'est pas du luxe).
Et si tu veux vraiment faire dans l'ultra hard core, en plus de ta matrice, tu te réserves n pointeurs sur (int *), que tu feras pointer sur le début de chaque lignes de ta matrice. Du coup :
* initialisation à 0 avec un memset
* possibilité d'accéder à un élément via tab[i][j] plutôt que tab[i * m + j]
* Libération avec un seul free.
Marsh Posté le 06-12-2007 à 06:22:54
tpierron a écrit : Dans ta boucle sur j, j'itérerai jusqu'à m et non n. |
alalaaa le copié-collé ça joue des tours ...
merci je n'avais pas remarqué !
bon je vais essayé toutes ces modifs !
Marsh Posté le 06-12-2007 à 09:00:52
@tpierron:
Le modéle H*W + acces en i+j*h est extrement peu performant.
Il est plus efficace et plus simple d'allouer un tableau 1D de H*W éléments puis de l'attaquer avec un tableau de pointeur de H éléments, chacun pointant sur le début d ela colonne correspondante.
Marsh Posté le 06-12-2007 à 12:25:13
Joel F a écrit : Le modéle H*W + acces en i+j*h est extrement peu performant. |
Qu'est-ce qui te fais dire ça ? Je pense que dans la pluspart des cas allouer un bloc mémoire et calculer les offsets sera au contraire plus rapide qu'allouer n blocs, et aller déréférencer une adresse à chaque accès.
Marsh Posté le 06-12-2007 à 12:32:06
tu veut creer un tableau HxW :
tu alloue un bloc de HxW elements
tu allour un tablea de H pointeurs
tu remplis ce tableau avec les offsets de colonnes.
Moralité :
tu accédes en T[i][j]
tu n'as qu'un bloc contigue (bon pr le cache)
Et ce qui me fait dire ça : ma thése sur le sujet + 2 ans de travaux en Traitement d'images haute performances
Le truc A NE PAS FAIRE : allouer un tableau de pointeur et allouer W pointeur differents discontinues
Marsh Posté le 06-12-2007 à 20:26:00
il est possible d'optimiser le calcul de produit de matrices en transposant la deuxieme matrice !
Le gain en performance est assez interessant pour des grosses matrices mais pas pour des petites matrices
Marsh Posté le 06-12-2007 à 20:38:01
transposition matrice NxM = NxM load + NxM store ....
le gain devient bon quand le gain du à la localité dans le cache devient superieure à 2NM donc ?
Marsh Posté le 06-12-2007 à 22:17:38
Qu'est-ce qui pose problème dans le fait d'allouer plusieurs pointeurs (pour chaque ligne) sur plusieurs emplacements mémoire discontinus?
Marsh Posté le 06-12-2007 à 22:23:00
si tes empalcements sont discontinu, tu va pourrir ton cache à chaque fin de ligne. Si ton bloc est continu (et que tu fais un beau tiling) tu mlinimises les sorties de cache.
et ca c'ets bien pour la planète
Marsh Posté le 06-12-2007 à 22:25:14
C'est quoi le cache et le tiling? Le cache c'est la mémoire cache du proc?
Marsh Posté le 06-12-2007 à 22:37:03
oui. le tiling c'est une technique qui consiste à travailler non pas sur les elements de ton tableau un par un mais par groupe de zone polygonale.
En general tu ecris
Code :
|
c'ets - bon que :
Code :
|
Dans le 2e cas, tu maximise la localité de tes données dans le cache et limite les cache miss. On démotnre (enfin les matheux démontre) que la forme de tile optimale ets une bouel carrée, donc ici un rectangle ou un carré.
La j'ai ecris à la va-vite. LE vrai code ne fait pas de *8 masi juste des += 8
Marsh Posté le 06-12-2007 à 23:40:24
Je suis pas sûr de bien avoir compris comment tu procèdes Joel. T c'est le tableau de H pointeurs, c'est ça ? Dans ce cas pour accéder à T[i][j] tu va d'abord lire l'adresse en T[i] (l'adresse de ta colonne), puis ensuite la valeur à cette adresse + j ? Comment ça peux être plus rapide qu'aller simplement lire la valeur à l'adresse B + H*i+j où B est ton bloc de H*W éléments (bloc contigu dans les deux cas) ? Surtout que la plupart des proc on un instruction qui fait mul et add en un coup ?
Marsh Posté le 06-12-2007 à 23:59:41
bon pour vous expliquer j'ai un projet à réaliser, le sujet est le suivant :
j'ai une blatte qui se trouve sur du carrelage aux dimensions de n x m (défini par l'utilisateur).
Le but est d'afficher lorsque la blatte est passée 3 fois sur chacun des carreaux. au bout de 50 000 déplacement la blatte s'arrete et on renvoi un message qui indique que les test n'a pas été réalisé.
Voila ce que j'ai fait... cependant des erreurs subsistent...
Pourriez vous m'aider ? Merci
Marsh Posté le 07-12-2007 à 02:35:19
Deja, cette partie la:
Citation : while((imove[r]+ibug<0) || (jmove[r]+jbug<0) || (imove[r]+ibug>=n) || (jmove[r]+jbug>=m)) |
Devrait être dans une grande boucle que tu iteres 50 000 fois, non?
Parce que la, avec ton code, ta bete fait un deplacement et c'est fini.
D'autre part
Citation : //Test sur toutes les valeurs du tableau count si 3 passages |
Tu teste si elle est passée exactement trois fois sur chaque case. A priori, ca devrait être au moins trois fois, non?
A+,
Marsh Posté le 07-12-2007 à 07:03:30
ah oui ! merci beaucoup je fais les modifications de suite !
il me reste plus qu'un problème je pense, c'est qui si je met dans la boucle je ne sortirais de celle ci que lorsque les 50 000 auront été atteind hors il faut que j'en sorte aussi si il y a au moins 3 passages dans chacune des cases. voici les modifications :
je pense que je dois inclure mon test des 3 passages dans la boucle mais je ne vois pas trop comment faire pour qu'elle pousse la boucle a se terminer...
Merci beaucoup pour l'aide !
Marsh Posté le 07-12-2007 à 11:51:49
Tu veux dire que tu peux t'arreter des que la bete est passee 3 fois partout?
C'est facile: avant ta grande boucle, tu met une variable a 0 qui va compter le nb de case ou la bete est passée 3 fois
apres avoir fait count[ibug][jbug] = count[ibug][jbug] + 1;
si maintenant count[ibug][jbug] == 3, tu incremente ta variable.
quand ta variable vaut m*n la bebete est passe 3 fois partout.
Tu peux donc faire un test d'arret de ta boucle avec 50000 tours ou bien ta variable == m*n
Et tu peux donc virer ton test sur toutes les valeurs du tableau count si 3 passages qui suit la boucle.
A+,
Marsh Posté le 07-12-2007 à 12:15:47
voila les modification apportées... ça ne marche pas... je ne vois pas pourquoi !
celà doit etre due à une petite erreur...
Marsh Posté le 07-12-2007 à 15:27:17
Citation : while(ok < (n*m) || k < 50000) |
Ca ne me semble pas d'une efficacité parfaite ce test...
Tu ne t'arreteras jamais avant les 50000 tours.
De plus k ne me semble pas être initialisé dans ton code.
A+,
Marsh Posté le 07-12-2007 à 17:58:31
C'est bon j'ai fais les modifs et tout fonctionne !!!! :-)
Merci beaucoup pour tous ces conseils !!!
A locker ! :-)
Geoffrey
Marsh Posté le 07-12-2007 à 21:52:38
Bon eh bien tant mieux.
Je me suis amusé a coder cela avec une variante sur le trajet aléatoire de la bestiole afin de ne pas générer de mouvements impossibles qui sont rejetés par la suite.
Ce qui est marrant, c'est que si tu fais aller la bestiole de maniere totallement aléatoire (ie la position d'une case a la suivante au hasard) c'est bien plus rapide que s'il ne change de trajectoire qu'en rencontrant un bord (ce que fait ta solution, au vu de ton code, a priori)
Code :
|
A+,
Marsh Posté le 08-12-2007 à 00:18:18
matafan a écrit : Je suis pas sûr de bien avoir compris comment tu procèdes Joel. T c'est le tableau de H pointeurs, c'est ça ? Dans ce cas pour accéder à T[i][j] tu va d'abord lire l'adresse en T[i] (l'adresse de ta colonne), puis ensuite la valeur à cette adresse + j ? Comment ça peux être plus rapide qu'aller simplement lire la valeur à l'adresse B + H*i+j où B est ton bloc de H*W éléments (bloc contigu dans les deux cas) ? Surtout que la plupart des proc on un instruction qui fait mul et add en un coup ? |
En gros :
Code :
|
L'acces T[i][j] avec cette methode ne necessite qu'une addition, et non pas une addition + une multiplication. Fait le test toi-même tu verras. J'etait persuadé du contraire jusqu'à ce que je fasse l'essai, que je bench et que j'etudie l'assembleur généré dasn ce cas et le cas t[i+j*H] sous intel et PPC, gcc, Visual ou icc.
En fait, t[i+j*] ca n'utilise pas de madd (surtout parce que n'a n'existe pas en scalaire) mais des blagues avec des MOV et des LEA ... et LEA <<< ADD
Pour ref, c'est la méthode préconisée par Numerical Recipes.
Marsh Posté le 08-12-2007 à 21:53:55
Joel F a écrit : tu veut creer un tableau HxW : |
Amen
Mais boost ?
Marsh Posté le 08-12-2007 à 21:57:44
Joel F a écrit :
|
Toi t'as jamais vu des vrais gars de la fac faire des i x 3 en allouant bien chaque float[3] à coup de malloc. Un régal. "bah pourquoi tu fais de la merde comme ça ? - bah je fais pareil en java"
Marsh Posté le 08-12-2007 à 22:01:35
(au fait ton truc est pas bon, faut passer par un typedef)
Marsh Posté le 09-12-2007 à 00:01:47
multi_array. J'ai jamais regardé l'alloc, mais le code généré à l'accès aux éléments est le bon (je l'avais prouvé dans un topic là dessus).
Marsh Posté le 09-12-2007 à 14:11:29
Taz a écrit : multi_array. J'ai jamais regardé l'alloc, mais le code généré à l'accès aux éléments est le bon (je l'avais prouvé dans un topic là dessus). |
lien? stp
Marsh Posté le 09-12-2007 à 16:29:44
j'aurais aimé savoir si a partir du codage ci dessous il était possible de faire un affichage graphique indiquant toutes les cases et le nombre de passage à l'intérieur ? merci
Code :
|
Marsh Posté le 09-12-2007 à 16:51:27
Adaptes celle de ce que j'ai donné en exemple, c'est pas bien dur.
Code :
|
A+,
Marsh Posté le 09-12-2007 à 16:58:55
voila ce que j'ai fait ... mais ça ne marche pas... peut tu m'expliquer pourquoi ?
Code :
|
aussi que qignifit cette ligne ?
Citation : printf("| %.5d ", board->squares[i][j]); |
merci infiniment !
Marsh Posté le 09-12-2007 à 18:37:51
Taz a écrit : multi_array. J'ai jamais regardé l'alloc, mais le code généré à l'accès aux éléments est le bon (je l'avais prouvé dans un topic là dessus). |
ouais je sais. J'ai besoin de plus que ça pour gérer mes Expr. templates et mon code de parallelisation automatique
Marsh Posté le 09-12-2007 à 21:18:11
yokooo a écrit :
|
printf, tu connais je suppose.
j'imprimes un | un espace, le nombre de fois qu'on est passe dans la case [i][j] du tableau, puis un autre espace.
Ce qui fait qu'en faisant ca pour tous les element d'une ligne, ca donne quelque chose de la forme:
| 00111 | 00022 | 03321 | 00001
il faut donc aussi imprimer un | avant de passer a la ligne suivante.
le %.5d sert a avoir des cases de taille constante, tous les nombres etant imprimés avec 5 chiffres.
Le 5 est choisi parce que au maximum, le valeur dans une cas eest 50000, ce qui tient sur 5 chiffres.
Si au lieu de copier coller betement mon code, tu avais essayé de comprendre ce qu'il fait, tu aurais vu qur mon int **squares correspond a ton int **count, et tu aurais adapté le code d'impression. Parce que la, il n'y a aucune chance que ca marche, avec le copier coller de la fonction que tu as fait.
Il ne faudrait peut etre pas esperer que je recode la fonction a ta place, ce n'est pas le principe de ce forum.
A+,
Marsh Posté le 09-12-2007 à 21:44:02
Taz a écrit : multi_array. J'ai jamais regardé l'alloc, mais le code généré à l'accès aux éléments est le bon (je l'avais prouvé dans un topic là dessus). |
T'es sur ?? Quand je vois ça :
Code :
|
J'en doute :s
Marsh Posté le 09-12-2007 à 22:43:32
ah oui effectivement j'avais oublié de changer le squares...
bon j'ai tout repris en modifiant ce qu'il fallait mais il me reste une erreur de syntaxe...
Code :
|
et les erreurs sont :
Citation : 20 : invalid use of array with unspecified bounds |
Marsh Posté le 10-12-2007 à 11:10:27
yokooo a écrit : ah oui effectivement j'avais oublié de changer le squares...
|
Tu fais un passage de parametre par addresse:
afficher(&count,n,m);
Il faut donc que ce soit le cas avec ta fonction:
void afficher(int (*count)[][], int n, int m)
ou
void afficher(int ***count, int n, int m)
si ton compilo n'aime pas la précédente déclaration.
et dans cette fonction, tu modifies les appels en appelant le tableau pointé
printf("| %.5d ", (*count)[i][j]);
A+,
Marsh Posté le 10-12-2007 à 13:04:32
ok c'est bon le programme se compile, mais...
il ne fonctionne pas...
il me dit que la blatte est passée sur tous les carreaux mais lors de l'affichage des cases il y en a certaines qui indiquent zéro...
Marsh Posté le 10-12-2007 à 21:26:40
yokooo a écrit : ok c'est bon le programme se compile, mais... |
Normal, vu qu'en ecrivant ton code, tu fais n'importe quoi:
Citation : if (count[ibug][jbug] != 0) |
C'est quoi la condition pour pouvoir incrementer ok??
A priori, avec ce code, tu dois jamais depasser les 2*m*n iterations.
A+,
Marsh Posté le 06-12-2007 à 00:32:56
Bonsoir,
je vous explique mon problème, je suis entrain de réaliser un programme dans le quel l'opérateur va rentrer deux valeurs qui correspondent aux nombres de lignes du tableau et aux nombres de colonnes, aussi je dois reinitialiser le tableau en mettant des 0 partout.
Je ne sais donc pas comment modifier la taille des lignes et des colonnes du tableau dans le programme en fonction de n et m...
Actuellement j'ai ça :
int **tab;
tab = malloc(n*sizeof(int));
for (i=0;i<n;i++)
{
_____tab[i] = malloc(m*sizeof(int));
_____for (j=0;j<n;j++)
_____{
__________tab[i][j]=0;
__________//printf("%d",tab[i][j]);
_____}
}
si vous pouviez m'aider ça serait super !
Merci beaucoup
P.S: Si vous n'avez pas compris ce que je souhaite faites le moi savoir
Message édité par yokooo le 06-12-2007 à 01:54:49