optimisation du code: quel est le principe ? - Programmation
Marsh Posté le 26-02-2001 à 11:36:57
Pour définir les triangles en tant que 3 indices parmi une liste de sommets (si j'ai bien compris ce que tu veux), utilise le type de primitive D3DPT_TRIANGLELIST.
En fait tu lui passes un tableau de WORD, chaque triplet correspondant à un triangle.
Pour la génération des fichiers x y'a une moulinette de conversion dans les SDK 7 (dans le 8 je crois bien que ça n'existe même plus). Ca marche assez moyennement, voire pas du tout parfois. Laisse tomber le format x ...
Marsh Posté le 26-02-2001 à 12:44:32
aïe malheureusement ce n'est justement pas ça que je demandais, ça je sais le faire (excume-moi c probablement de ma faute mais j'ai toujours un mal fou à me faire comprendre )... en fait ce que je demande c, une fois que tu as fait ton tableau de matrices comment faire pour définir les triangles en spécifiant une liste de sommet (par exemple si je veux un triangle formé des sommet 4, 7 et 3 je passe la liste 4,7,3 ... comme avac un D3DRMBuilder dans DirectX7, mais je veux le faire avec un objet Direct3D8)...
pour la moulinette de conversion, ya rien d'autre ?? alors ya peut-être un autre format que les ".x", enfin ya bien un moyen d'importer ses mesh kan même ?
merci qz51 pour ta réponse, j'espère que tu seras pas le seul à me répondre !
Marsh Posté le 26-02-2001 à 16:35:33
Tu veux dire générer les triangles automatiquement à partir des sommets ? Comment veux-tu faire ça, y'a pas qu'une seule possibilité ... ça fait partie de la description géométrique d'un objet, tu ne peux pas le déduire de la liste des sommets
(à la différence des normales qui elles peuvent être calculées).
Si c'est pas ça, j'ai encore pas compris ce que tu voulais exactement.
--Message édité par z51--
Marsh Posté le 26-02-2001 à 19:25:45
non non, je veus dire comment définir des triangles avec des énumérations de sommets... comme avec les 'builders' de directX7.0, ah.. malheureusement je n'ai pas le SDK et les sources ici (je poste du PC de mes parents)... je vois pas trop comment t'expliquer. mais normalement pour définir un polygone t'as plusieurs choix :
-celui dont tu me parlais tout à l'heure (avec le flag "3DTPS_TRIANGLELIST" ou un truc du genre, ya aussu "TRIANGLE_STRIP" qui n'interprète pas les sommets de la même manière)
-une autre qui consiste à énumérer les indices des sommets décrivant les triangles (indispensable pour faire des polygones un peu plus complexes)
-puis yen a ptêt d'autre, j'en sais rien je débute ...
moi c la deuxième méthode qui m'intéresse, je sais qu'elle existe, j'avais vu un source qui le faisait mais à l'aide d'un objet D3DRM, ça ne m'intéresse pas de passer par un D3DRM car Direct3D8 est bien + simple et je ne veux me servir que de ça...
d'ailleurs quelle est la diférence entre D3DRM et D3DIM ?
Marsh Posté le 27-02-2001 à 15:30:30
n'y-a-t-il pas un tueur en programmation sur ce forum qui puisse me répondre ??
(j'espère que ça va susciter des réponses )
Marsh Posté le 27-02-2001 à 19:27:10
Concernant les optimisations faites par les compilateurs, il y a toute une littérature sur le sujet.
Globalement, on peut distinguer les optimisations locales et les optimisations globales. Les premières sont évidemment les moins difficiles à mettre en oeuvre.
Les optimisations locales sont généralement appelées des optimisations "à lucarne", c'est-à-dire qu'on regarde chaque petit bout de code généré à la loupe (ou par la lucarne, d'où l'expression), pour voir si on ne peut pas reconnaître des motifs facilement optimisables. Typiquement, des sous-expressions constantes, ou du code constant exécuté plusieurs fois (au sein d'une boucle par exemple). Ou bien, une valeur affectée à une variable, qu'on n'utilise pas ensuite (on peut alors la supprimer).
Tu remarqueras que ces optimisations sont valables quel que soit le processeur. D'autres optimisations, encore plus locales, et éventuellement propre au processeur pour lequel on génère du code machine, peuvent être intéressantes. Par exemple sur l'Intel 8086, l'instruction assembleur "MOV AX, 0" était moins rapide (et en plus était plus grosse) que "XOR AX, AX". Comme ces 2 instructions ont le même effet, on utilisait plutôt la deuxième à la place de la première.
Enfin, d'autres optimisations font du réordonnancement. Par exemple, si tu écris : "i = 0; j = 0; i = i + 1;", le compilateur peut constater que les instructions 2 et 3 sont indépendantes et peuvent donc être échangées. Comme les variables i et j vont être mises dans un registre pour être manipulées, il peut être plus efficace de réordonnancer ce code en "i = 0; i = i + 1; j = 0;", ce qui évitera d'écrire i (valant 0) en mémoire, puis de re-rapatrier i depuis la mémoire vers un registre (pour lui affecter 1). Deux échanges mémoire <--> registre processeur économisés, c'est toujours bon à prendre. Surtout si ce code est exécuté plein de fois...
Le principal avantage des optimisations à lucarne est que l'on peut les enchaîner. Par exemple, avec une analyse par graphe, un compilateur (assez intelligent, il faut le reconnaître) peut voir que le code ci-dessus, une fois réordonnancé, peut être réécrit "i = 0 + 1; j = 0;", puisque i a une valeur prévisible dans la 2ème affectation (zéro). Or, une 3ème optimisation peut être apportée, puis que 0 + 1 est une expression constante, et on va se retrouver avec le code généré "i = 1; j = 0;".
Autre type d'optimisation, permise seulement par certains langages. Il s'agit du code rajouté par les compilateurs.
Par exemple, en Pascal, pour parcourir un tableau tab, on écrit:
var i: integer;
for i := 0 to N do begin
tab[ i] := ...;
end;
Si le compilateur est "sûr", il va générer, à chaque fois qu'on accède au tableau, un peu de code pour vérifier qu'on ne déborde pas du tableau (histoire d'éviter des bugs mémoire tordus). En Ada, on va plutôt écrire:
for i in tab'Range loop
tab(i) := ...;
end loop;
Ici, le compilateur a la garantie que l'indice de boucle ne sortira pas des bornes du tableau, donc le code de vérification de l'indice peut être supprimé !
Les optimisations globales sont beaucoup plus délicates (et je connais nettement moins). Dans cette catégorie peut être aussi rangé le réordonnancement de code, mais en général, l'échelle est toute autre. Par exemple, soit la boucle C suivante :
for (int i = 0; i < 1000; i++) {
for (int k = 0; k < 5; k++) {
tab[k][ i] = 0;
}
}
Si la mémoire est paginée par pages de 1000 mots par exemple, chaque itération de la boucle extérieure accèdera à toutes les pages, ce qui est coûteux. Le code suivant lui sera strictement équivalent, mais chaque page ne sera accédée qu'une seule fois avant d'être chassée par la suivante :
for (int k = 0; k < 5; k++) {
for (int i = 0; i < 1000; i++) {
tab[k][ i] = 0;
}
}
Il sera donc (de loin) beaucoup plus rapide.
Enfin, pour les compilateurs les plus performants (genre compilateurs générant du code parallèle), on peut essayer de voir quels sont les instructions qui sont complètement indépendantes pour essayer de les faire exécuter en même temps par le processeur (ce qui est possible si, en particulier, les fonctions du processeur utilisées par ces instructions sont aussi différentes. Genre, une instruction mathémtique en même temps qu'une instruction arithmétique sur des entiers).
C'est d'ailleurs, si je ne me trompe pas, ce qu'essaient de faire les processeurs les plus récents (avec leur architecture pipelinée et leur analyseur prédictif).
En espérant que cela t'aura éclairé un peu...
Marsh Posté le 27-02-2001 à 19:46:24
merci BifaceMcLeOD pour ta réponse ! c sympa d'avoir enfin une réponse !
ya un ptit "mais", c k'en fait ce que je cherche ce sont d'abord des explications sur les principes de fonctionnement de ces algos d'optimisation (comment le compilateur à l'aide de graphes detecte-t-il les motifs à optimiser, etc...), je connais les optimisations elles-mêmes, mais je ne sais pas réellement quel est le méchanisme interne au compilateur. Tout juste sais-je qu'il y a des utilisations de graphes ! Tu parlais de revues sur le sujet, peut-être as-tu des liens sur des sites qui traitent du sujet. En tout cas merci encore pour ta longue réponse. Elle n'est pas inutile rassure-toi, tu m'as déjà appris quelques trucs !
--Message édité par ZZZzzz--
Marsh Posté le 27-02-2001 à 20:12:52
Pour en revenir aux primitives Direct X ... (bonjour les sujets croisés ... t'aurais p'tet du créer deux sujets)
Mis à part D3DPT_TRIANGLELIST et D3DPT_TRIANGLESTRIP que tu évoques, il y a D3DPT_TRIANGLEFAN, dérivée du strip mais avec un même sommet référencé dans chaque triangle. La meilleure utilisation qu'on peut en faire c'est pour définir un cône (c'est d'ailleurs l'exemple choisi dans le SDK).
Je doute que ce soit ce que tu recherches ...
Le mode retenu est une API basée sur Direct 3D. La différence principale est que tu n'y gères plus directement des vertices, des triangles et des surfaces, mais directement des objets : objet mesh, objet texture, objet lumière... avec bien sûr toute la panoplie des méthodes dédiées.
Ce mode semble avoir disparu du SDK8, au profit de D3DX.
Marsh Posté le 27-02-2001 à 23:07:56
ah ben merde comment que je défini mon cube moi maintenant ??
pour le param "TRIANGLEFAN" , ce n'est effectivement pas ce que je recherche... comment faire alors pour définir un simple cube avec Direct3D8 autrement qu'en passant par un mesh ??
comme tu dis D3D8 se sert plus de D3DX , les matrices utilisées par exemple par D3D8 sont des objets dont les opérateurs ont été redéfini et comprennant beaucoup de fonctions de traitement... cela simplifie la programmation (par rapport aux anciennes matrices où il fallait implémenter les opérations de base soit-même comme la multiplication, etc...) au détriment des performances (enfin je fais confiance aux professionnels qui ont développés DirectX, leur algos doivent êtes 'achement optimisés)
Bon j'attends toujours de l'aide d'un Dieu de la programmation ...
Marsh Posté le 27-02-2001 à 23:08:28
ZZZzzz> A vrai dire, je n'ai jamais rien lu d'autre que les concepts généraux. Après, la question est simplement comment représenter le code pour qu'on puisse facilement reconnaître les motifs recherchés (mais ça, ce n'est pas nouveau, c'est un problème général en programmation). Et c'est là où les arbres ou les graphes sont utiles.
Je peux te donner un exemple (simplifié), pour un programme que j'ai moi-même écrit. En l'occurrence, il s'agissait de représenter, sous forme d'arbre, une expression mathématique.
Exemple : (2 + 3) * 0, devient :
*
/ \
+ 0
/ \
2 3
Une des optimisations possibles est 0 * (ce-que-tu-veux) = 0. Donc, il suffit de reconnaître, un noeud "0" avec son parent contenant un produit pour dire "OK, on remplacer tout ce sous-arbre par xxxx". En l'occurrence, une feuille contenant simplement zéro.
Si tu as compris ça, les techniques d'optimisation du code les plus évoluées te seront accessibles (et tu devrais même pouvoir les trouver tout seul... ).
--Message édité par BifaceMcLeOD--
Marsh Posté le 27-02-2001 à 23:32:55
c si simple ??
moi qui m'attendais à des graphes valués avec des algos de la mort de recherche du plus court chemin et le moins coûteux, ou des B-arbres avec reéquilibrage, etc... bref le genre de conneries que j'ai normalement étudié (c un bien grand mot finalement, j'oublie systématiquement ce qui me semble inutile, or tous mes cours me semble inutiles, donc je n'en retiens pas grand chose...) !!
J'ai déjà vu ce genre de notation, très souvent même, et selon que l'on parcours l'arbre en largeur ou en profondeur on a une notation normale (la notre) ou en RPN (notation polonaise, les HP48 fonctionnaient avec la notation polonaise inversée, cété vachement pratique avec le système de pile).
et bien je te remerci BifaceMcLeOD, tu me rassures !!!!
bon il me reste mon problème avec Direct3D 8, quel est le Sur-Dieu qui pourra me répondre ?
--Message édité par ZZZzzz--
Marsh Posté le 25-02-2001 à 18:56:46
Voilà j'aimerai savoir comment le principe d'optimisation du code (dans un compilateur c par exemple). Attention je ne veux pas savoir comment on optimise son code (ça je le sais déjà, enfin à peu près), je veut juste connaitre els mécanisme employés par les compilateurs pour optimiser le code durant la compilation. Je sais qu'il y a une histoire avec des graphes, etc.. mais c tout ! alors s'il quelqu'un connait bien le sujet ou aurait un ptit like à me refiler ça serait très sympa !
De même je cherche un moyen en Direct3D 8 de faire des objets 3D (comme des cubes) dont les triangles peuvent être défini à partir d'une suite de vertices (sommets), je sais crée des objets à partir de vertices mêmes (je donne la suite des vertices et ensuite les vertices sont directement interprétés d'une certaine manière selon les flags que l'on passe en param. pour construire les triangles) ou à partir de mesh contenu dans des fichiers ".x", mais je sais pas définir les triangles à partir de certains vertices, du coup je sais pas faire un cube(à moins d'avoir des triangles qui se chevauchent).
encore 2 petites questions:
-comment définir plusieurs objets 3D sous Direct8 (je veux faire un cube et un sphère par exemple, indépendant l'un de l'autre)?
-et enfin peut-on crée un fichier ".x" directement avec une application de rendu 3D (j'ai essayé avec 3DSMAX mais apparement on ne peut pas le faire de base, faut-il un plugin ?) ?
voilà, merci à vous !