J'ai entrepris d'écrire un programme de jeu d'Echecs. Je suis venu à bout,
non sans mal, des préliminaires imposés: définition des règles de
déplacement des pièces, interface graphique pour les déplacer,
enregistrement écrit des coups joués et déplacement dans la partie par des
boutons avant / arrière.
J'en suis maintenant au vif du sujet, à savoir la recherche du meilleur coup
au moyen de l'algorithme MinMax avec coupures alpha-beta.
La difficulté vient de ce que cet algorithme est récursif. Voici sa
structure.
"pos" décrit l'échiquier sur 84 octets." minDepth" est la profondeur en
demi-coups à laquelle on limite la recherche. "alpha" est une limite
inférieure du score et "beta" une limite supérieure. Au fil de itérations,
la fourchette alpha beta se rétrécit:
/**********************************************************************/
if (alphaPos < moveScore) //alphaPos = Max (alphaPos, moveScore);
alphaPos = moveScore;
if (alphaPos >= B)
return alphaPos; //coupure beta;
}
return alphaPos;
}
(Cet extrait ne comporte que la partie Max. La partie Min est symétrique et
concerne les coups de l'adversaire.)
Comme une position donne lieu en moyenne à 30 coups possibles, la récursion
est intense. une exploration totale sur une profondeur 4 donnerait lieu à
810 000 appel de MinMax. La coupure alpha-beta limite de 5/6 fois ce nombre,
mais je suis parvenu à 76000 appels sur une profondeur 4, en 4 minutes 38''
Le problème que je rencontre alors est que quand je devrais reprendre la
main, j'obtiens la roulette arc-en-ciel si longtemps que je suis obligé de
forcer le Quit...
Je me suis livré à un examen via ObjectAlloc qui donne ceci:
-Au départ, programme initialisé: Global allocation Total, Current = 1.9 Mo
-Pendant la recherche du premier coup blanc 1.Cc3, trouvé en 3 sec. et <
2000 appels de MinMax (Hors ObjectAlloc), Global allocation Total, Current
atteint 17 Mo puis revient à sa valeur initiale.
-Pendant la recherche de la réponse noire 1...c7-c6 (bizarre comme
ouverture... trouvé en 12" et < 6000 appels) Global allocation Total,
Current atteint 64 Mo puis revient à 5,3 Mo (Memory leakage possible...)
Si j'extrapole vers la situation où le programme trouve une bonne réfutation
à une menace de mat en 2 coups en 4' 38" et 76000 appels de MinMax , cela
donne 800Mo d'allocation courante! (Pour les initiés, il s'agit du Mat de
Legal, où les Blancs offrent leur Dame pour faire ensuite Mat en deux coups.
Normal que le programme aie pris son temps avant de renoncer au cadeau)
J'ai installé un pool d'autoRelease, mais c'est complètement inopérant. Si
je comprends bien ça doit être normal, puisqu'on ne sort pas de l'EventLoop
tant que la récursion est en cours.
Merci à qui a eu la patience de me lire, et plus encore à qui pourrait
m'indiquer la bonne méthode pour gérer proprement les désallocations.
Mes premiers résultats sont encourageants et ça m'ennuie d'être bloqué par
ce problème.
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
jeromelebel
Louis Balourdet wrote:
Le problème que je rencontre alors est que quand je devrais reprendre la main, j'obtiens la roulette arc-en-ciel si longtemps que je suis obligé de forcer le Quit...
Fait tourné ton algo dans un deuxième thread afin que l'utilisateur ai la main et puisse arrêter les calculs en cours.
J'ai installé un pool d'autoRelease, mais c'est complètement inopérant. Si je comprends bien ça doit être normal, puisqu'on ne sort pas de l'EventLoop tant que la récursion est en cours.
Crée ta pool en début de minMax:minDepth:alpha:beta: et relache la en fin de méthode. Si tu veux optimiser un peu éviter l'utilisation -[NSString componentsSeparatedByString:] (et autres méthodes qui te renvoie des object dans la pool d'autorelease, car tu ne peux pas controller la déallocation directement) et ca t'évitera l'utilisation de pool d'autorelease à chaque fois que tu appeles ta méthode (ce qui doit être très fréquent !).
De plus, essaye l'outil "Shark", ca devrait beaucoup t'aider !
Louis Balourdet <L.Balourdet@wanadoo.fr> wrote:
Le problème que je rencontre alors est que quand je devrais reprendre la
main, j'obtiens la roulette arc-en-ciel si longtemps que je suis obligé de
forcer le Quit...
Fait tourné ton algo dans un deuxième thread afin que l'utilisateur ai
la main et puisse arrêter les calculs en cours.
J'ai installé un pool d'autoRelease, mais c'est complètement inopérant. Si
je comprends bien ça doit être normal, puisqu'on ne sort pas de l'EventLoop
tant que la récursion est en cours.
Crée ta pool en début de minMax:minDepth:alpha:beta: et relache la en
fin de méthode. Si tu veux optimiser un peu éviter l'utilisation
-[NSString componentsSeparatedByString:] (et autres méthodes qui te
renvoie des object dans la pool d'autorelease, car tu ne peux pas
controller la déallocation directement) et ca t'évitera l'utilisation de
pool d'autorelease à chaque fois que tu appeles ta méthode (ce qui doit
être très fréquent !).
De plus, essaye l'outil "Shark", ca devrait beaucoup t'aider !
Le problème que je rencontre alors est que quand je devrais reprendre la main, j'obtiens la roulette arc-en-ciel si longtemps que je suis obligé de forcer le Quit...
Fait tourné ton algo dans un deuxième thread afin que l'utilisateur ai la main et puisse arrêter les calculs en cours.
J'ai installé un pool d'autoRelease, mais c'est complètement inopérant. Si je comprends bien ça doit être normal, puisqu'on ne sort pas de l'EventLoop tant que la récursion est en cours.
Crée ta pool en début de minMax:minDepth:alpha:beta: et relache la en fin de méthode. Si tu veux optimiser un peu éviter l'utilisation -[NSString componentsSeparatedByString:] (et autres méthodes qui te renvoie des object dans la pool d'autorelease, car tu ne peux pas controller la déallocation directement) et ca t'évitera l'utilisation de pool d'autorelease à chaque fois que tu appeles ta méthode (ce qui doit être très fréquent !).
De plus, essaye l'outil "Shark", ca devrait beaucoup t'aider !
Louis Balourdet
Fait tourné ton algo dans un deuxième thread afin que l'utilisateur ai la main et puisse arrêter les calculs en cours.
Crée ta pool en début de minMax:minDepth:alpha:beta: et relache la en fin de méthode. Si tu veux optimiser un peu éviter l'utilisation -[NSString componentsSeparatedByString:] (et autres méthodes qui te renvoie des object dans la pool d'autorelease, car tu ne peux pas controller la déallocation directement) et ca t'évitera l'utilisation de pool d'autorelease à chaque fois que tu appeles ta méthode (ce qui doit être très fréquent !).
De plus, essaye l'outil "Shark", ca devrait beaucoup t'aider !
Merci pour ces explications. Je vais essayer d'installer un thread, bien que ça n'ai pas l'air très facile. L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Fait tourné ton algo dans un deuxième thread afin que l'utilisateur ai
la main et puisse arrêter les calculs en cours.
Crée ta pool en début de minMax:minDepth:alpha:beta: et relache la en
fin de méthode. Si tu veux optimiser un peu éviter l'utilisation
-[NSString componentsSeparatedByString:] (et autres méthodes qui te
renvoie des object dans la pool d'autorelease, car tu ne peux pas
controller la déallocation directement) et ca t'évitera l'utilisation de
pool d'autorelease à chaque fois que tu appeles ta méthode (ce qui doit
être très fréquent !).
De plus, essaye l'outil "Shark", ca devrait beaucoup t'aider !
Merci pour ces explications. Je vais essayer d'installer un thread, bien que
ça n'ai pas l'air très facile.
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project
Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Fait tourné ton algo dans un deuxième thread afin que l'utilisateur ai la main et puisse arrêter les calculs en cours.
Crée ta pool en début de minMax:minDepth:alpha:beta: et relache la en fin de méthode. Si tu veux optimiser un peu éviter l'utilisation -[NSString componentsSeparatedByString:] (et autres méthodes qui te renvoie des object dans la pool d'autorelease, car tu ne peux pas controller la déallocation directement) et ca t'évitera l'utilisation de pool d'autorelease à chaque fois que tu appeles ta méthode (ce qui doit être très fréquent !).
De plus, essaye l'outil "Shark", ca devrait beaucoup t'aider !
Merci pour ces explications. Je vais essayer d'installer un thread, bien que ça n'ai pas l'air très facile. L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
jeromelebel
Louis Balourdet wrote:
Merci pour ces explications. Je vais essayer d'installer un thread, bien que ça n'ai pas l'air très facile.
C'est pas tres compliqué : * utilise un booléen, "cancel", que tu passes à vrai des que tu veux annuler ton calcul * vérifie ce booléen dans ton algo plus ou moins fréquement (genre dans ta boucle "for" que tu as donné) et arrête des qu'il est a vrai * dans ton UI, lorsque l'utilisateur clique sur "cancel", passe ton booléen, "cancel", à vrai * utilise +[NSThread detachNewThreadSelector:toTarget:withObject:] pour créer un thread * dès que ton calcul est fini, passe un autre booléen "done" à vrai * quand tu lances ton thread de calcul, -[NSObject performSelector:withObject:afterDelay:] pour savoir quand ton calcul est fini (sur panther, il y a un moyen beaucoup plus propre de faire ca...), et appele cette méthode avec un délai de .5 secondes (en gros). * evidement, initialise correctement "done" et "cancel", de plus n'oublie pas de désactiver certaine partie de ton UI pour éviter que l'utilisateur puisse jouer pendant que l'ordinateur réflichi
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
Louis Balourdet <L.Balourdet@wanadoo.fr> wrote:
Merci pour ces explications. Je vais essayer d'installer un thread, bien que
ça n'ai pas l'air très facile.
C'est pas tres compliqué :
* utilise un booléen, "cancel", que tu passes à vrai des que tu veux
annuler ton calcul
* vérifie ce booléen dans ton algo plus ou moins fréquement (genre dans
ta boucle "for" que tu as donné) et arrête des qu'il est a vrai
* dans ton UI, lorsque l'utilisateur clique sur "cancel", passe ton
booléen, "cancel", à vrai
* utilise +[NSThread detachNewThreadSelector:toTarget:withObject:] pour
créer un thread
* dès que ton calcul est fini, passe un autre booléen "done" à vrai
* quand tu lances ton thread de calcul, -[NSObject
performSelector:withObject:afterDelay:] pour savoir quand ton calcul est
fini (sur panther, il y a un moyen beaucoup plus propre de faire ca...),
et appele cette méthode avec un délai de .5 secondes (en gros).
* evidement, initialise correctement "done" et "cancel", de plus
n'oublie pas de désactiver certaine partie de ton UI pour éviter que
l'utilisateur puisse jouer pendant que l'ordinateur réflichi
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project
Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Merci pour ces explications. Je vais essayer d'installer un thread, bien que ça n'ai pas l'air très facile.
C'est pas tres compliqué : * utilise un booléen, "cancel", que tu passes à vrai des que tu veux annuler ton calcul * vérifie ce booléen dans ton algo plus ou moins fréquement (genre dans ta boucle "for" que tu as donné) et arrête des qu'il est a vrai * dans ton UI, lorsque l'utilisateur clique sur "cancel", passe ton booléen, "cancel", à vrai * utilise +[NSThread detachNewThreadSelector:toTarget:withObject:] pour créer un thread * dès que ton calcul est fini, passe un autre booléen "done" à vrai * quand tu lances ton thread de calcul, -[NSObject performSelector:withObject:afterDelay:] pour savoir quand ton calcul est fini (sur panther, il y a un moyen beaucoup plus propre de faire ca...), et appele cette méthode avec un délai de .5 secondes (en gros). * evidement, initialise correctement "done" et "cancel", de plus n'oublie pas de désactiver certaine partie de ton UI pour éviter que l'utilisateur puisse jouer pendant que l'ordinateur réflichi
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
Frédéric Testuz
"Jérôme Lebel" a écrit dans le message de news:1gk20xa.10pioi0dz4c38N%
Louis Balourdet wrote:
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project
Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
De mon coté, je viens de faire une installation standard de Xcode 1.5 et Shark n'est pas présent.
-- Frédéric Testuz
"Jérôme Lebel" <jeromelebel@mac.com> a écrit dans le message de
news:1gk20xa.10pioi0dz4c38N%jeromelebel@mac.com...
Louis Balourdet <L.Balourdet@wanadoo.fr> wrote:
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous
Project
Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
De mon coté, je viens de faire une installation standard de Xcode 1.5 et
Shark n'est pas présent.
Ah, ben voilà, dans l'installation standard, les CHUD tools ne sont pas installé.
C'est vraiment utile ? De mon côté, je viens seulement de me mettre à ObjectAlloc. Je sais qu'il était temps ;-)
PS : je programme juste pour moi, donc je ne me préocuppais pas trop d'optimisation. -- Frédéric Testuz
jeromelebel
Frédéric Testuz wrote:
Ah, ben voilà, dans l'installation standard, les CHUD tools ne sont pas installé.
C'est vraiment utile ? De mon côté, je viens seulement de me mettre à ObjectAlloc. Je sais qu'il était temps ;-)
PS : je programme juste pour moi, donc je ne me préocuppais pas trop d'optimisation.
Ben je ne sais pas si ca existe pour 10.2. Ca peut toujours etre utile, ou sympa quand on est curieux. De plus, même si c'est personnel, on peut toujours avoir des gros problemes de perf.
Sinon, il y a toujours "sample" peut aider a savoir ce qu'il se passe...
Ah, ben voilà, dans l'installation standard, les CHUD tools ne sont pas
installé.
C'est vraiment utile ? De mon côté, je viens seulement de me mettre à
ObjectAlloc. Je sais qu'il était temps ;-)
PS : je programme juste pour moi, donc je ne me préocuppais pas trop
d'optimisation.
Ben je ne sais pas si ca existe pour 10.2.
Ca peut toujours etre utile, ou sympa quand on est curieux. De plus,
même si c'est personnel, on peut toujours avoir des gros problemes de
perf.
Sinon, il y a toujours "sample" peut aider a savoir ce qu'il se passe...
Ah, ben voilà, dans l'installation standard, les CHUD tools ne sont pas installé.
C'est vraiment utile ? De mon côté, je viens seulement de me mettre à ObjectAlloc. Je sais qu'il était temps ;-)
PS : je programme juste pour moi, donc je ne me préocuppais pas trop d'optimisation.
Ben je ne sais pas si ca existe pour 10.2. Ca peut toujours etre utile, ou sympa quand on est curieux. De plus, même si c'est personnel, on peut toujours avoir des gros problemes de perf.
Sinon, il y a toujours "sample" peut aider a savoir ce qu'il se passe...
Louis Balourdet
C'est pas tres compliqué : * utilise un booléen, "cancel", que tu passes à vrai des que tu veux annuler ton calcul * vérifie ce booléen dans ton algo plus ou moins fréquement (genre dans ta boucle "for" que tu as donné) et arrête des qu'il est a vrai * dans ton UI, lorsque l'utilisateur clique sur "cancel", passe ton booléen, "cancel", à vrai * utilise +[NSThread detachNewThreadSelector:toTarget:withObject:] pour créer un thread * dès que ton calcul est fini, passe un autre booléen "done" à vrai * quand tu lances ton thread de calcul, -[NSObject performSelector:withObject:afterDelay:] pour savoir quand ton calcul est fini (sur panther, il y a un moyen beaucoup plus propre de faire ca...), et appele cette méthode avec un délai de .5 secondes (en gros). * evidement, initialise correctement "done" et "cancel", de plus n'oublie pas de désactiver certaine partie de ton UI pour éviter que l'utilisateur puisse jouer pendant que l'ordinateur réflichi
Merci. Avec ces explications et les exemples de thread dans "Building Cocoa Applications" de Simon Garfinkel, je pense que je devrais m'en sortir.
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
Ce serait une raison de plus de m'upgrader vers Panther. Mais personnellement, j'évite les mises à jour tant que je peux m'en passer. Souvent ça résoud des problèmes qui ne me concernent pas, et ça en apporte de nouveaux qui eux me font perdre du temps. Pour l'instant je me dis que j'attendrai Tiger...
C'est pas tres compliqué :
* utilise un booléen, "cancel", que tu passes à vrai des que tu veux
annuler ton calcul
* vérifie ce booléen dans ton algo plus ou moins fréquement (genre dans
ta boucle "for" que tu as donné) et arrête des qu'il est a vrai
* dans ton UI, lorsque l'utilisateur clique sur "cancel", passe ton
booléen, "cancel", à vrai
* utilise +[NSThread detachNewThreadSelector:toTarget:withObject:] pour
créer un thread
* dès que ton calcul est fini, passe un autre booléen "done" à vrai
* quand tu lances ton thread de calcul, -[NSObject
performSelector:withObject:afterDelay:] pour savoir quand ton calcul est
fini (sur panther, il y a un moyen beaucoup plus propre de faire ca...),
et appele cette méthode avec un délai de .5 secondes (en gros).
* evidement, initialise correctement "done" et "cancel", de plus
n'oublie pas de désactiver certaine partie de ton UI pour éviter que
l'utilisateur puisse jouer pendant que l'ordinateur réflichi
Merci. Avec ces explications et les exemples de thread dans "Building Cocoa
Applications" de Simon Garfinkel, je pense que je devrais m'en sortir.
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project
Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
Ce serait une raison de plus de m'upgrader vers Panther. Mais
personnellement, j'évite les mises à jour tant que je peux m'en passer.
Souvent ça résoud des problèmes qui ne me concernent pas, et ça en apporte
de nouveaux qui eux me font perdre du temps. Pour l'instant je me dis que
j'attendrai Tiger...
C'est pas tres compliqué : * utilise un booléen, "cancel", que tu passes à vrai des que tu veux annuler ton calcul * vérifie ce booléen dans ton algo plus ou moins fréquement (genre dans ta boucle "for" que tu as donné) et arrête des qu'il est a vrai * dans ton UI, lorsque l'utilisateur clique sur "cancel", passe ton booléen, "cancel", à vrai * utilise +[NSThread detachNewThreadSelector:toTarget:withObject:] pour créer un thread * dès que ton calcul est fini, passe un autre booléen "done" à vrai * quand tu lances ton thread de calcul, -[NSObject performSelector:withObject:afterDelay:] pour savoir quand ton calcul est fini (sur panther, il y a un moyen beaucoup plus propre de faire ca...), et appele cette méthode avec un délai de .5 secondes (en gros). * evidement, initialise correctement "done" et "cancel", de plus n'oublie pas de désactiver certaine partie de ton UI pour éviter que l'utilisateur puisse jouer pendant que l'ordinateur réflichi
Merci. Avec ces explications et les exemples de thread dans "Building Cocoa Applications" de Simon Garfinkel, je pense que je devrais m'en sortir.
L'outil "Shark" ne figure pas dans ma panoplie. Je suis encore sous Project Builder et 10.2.6 . Est-ce qu'on le trouve dans les outils 10.3 ?
Oui, c'est exacte.
Ce serait une raison de plus de m'upgrader vers Panther. Mais personnellement, j'évite les mises à jour tant que je peux m'en passer. Souvent ça résoud des problèmes qui ne me concernent pas, et ça en apporte de nouveaux qui eux me font perdre du temps. Pour l'instant je me dis que j'attendrai Tiger...