Arrays in Templates: was macht der Compiler daraus?
-
Hallo DocShoe
Es geht um meine Schachengine, in der fast alle Algorithmen doppelt vorhanden sind. Also für Weiss und für Schwarz. Das Problem ist der redundante Code. Die Algorithmen unterscheiden sich ja nur geringfügig. Es müssen im Grunde nur die Reihen umgekehrt werden und der Gegner gespiegelt werden:
So ist es aktuell (Ausschnitt):
// white rook case PIECE_ROOK: board.key_pieces^=random_white_rook[from]; board.key_pieces^=random_white_rook[to]; board.white_rook_bitboard&=bitboard_clear[from]; board.white_rook_bitboard|=bitboard_set[to]; board.piece[to]=PIECE_WHITE_ROOK; board.moves[from]++; break; // black rook case PIECE_ROOK: board.key_pieces^=random_black_rook[from]; board.key_pieces^=random_black_rook[to]; board.black_rook_bitboard&=bitboard_clear[from]; board.black_rook_bitboard|=bitboard_set[to]; board.piece[to]=PIECE_BLACK_ROOK; board.moves[from]++; break;So könnte es aussehen (Ausschnitt):
// white rook / black rook case PIECE_ROOK: board.key_pieces^=random_rook[color][from]; board.key_pieces^=random_rook[color][to]; board.rook_bitboard[color]&=bitboard_clear[from]; board.rook_bitboard[color]|=bitboard_set[to]; board.piece[to]=piece_rook[color]; board.moves[from]++; break;Es sind etwa 80 Algorithmen die etwa 50% der gesamten Rechenzeit konsumieren. Wenn eine neue Konstruktion zwar weniger Codierungsaifwand bedeutet aber merklich langsamer ist (> 10%) habe ich nichts davon.
-
Nochmal ganz kurz:
**
A: Mein Ziel ist es die Codemenge zu reduzieren, damit ich Änderungen und Verbesserungen nicht immer doppelt codieren muss.B: Die Laufzeiteffizient soll aber nicht zu sehr darunter leiden
**
-
Da hilft nur eins: Untersuch das Laufzeitverhalten mit einem Profiler. Oder bau dir einen minmalen Anwendungsfall, der das Problem beeinhaltet und schau dir an, wieviel Zeit ein (10, 1.000, 1.000.000, 100.000.000) Durchlauf benötigt (unter Windows mit QueryPerformanceCounter/QueryPerformanceFrequency). Damit sollest du abschätzen können, ob es immer noch schnell genug ist.
-
Auch wenn ich mich meinen Vorrednern bezüglich frühzeitiger Optimierung anschließen möchte: Wenn du zwei fast gleiche Algorithmen hast, dann versuch das doch mit Templates zusammenzufassen. Templates werden zur Compilezeit ausgewertet. Entsprechend können auch Arrayzugriffe mit einem Templateparameter als Index zur Compilezeit ausgewertet werden.
-
Eben das war genau meine Frage bzw mein Vorschlag!
void make_move(int color, int turn, int move) { if (turn == WHITE) make_move_template<WHITE>(turn, move); else make_move_template<BLACK>(turn, move); } template<int color> void make_move_template(int turn, int move) { switch (piece(move)) { // ... case PIECE_ROOK: board.key_pieces^=random_rook[color][from]; board.key_pieces^=random_rook[color][to]; board.rook_bitboard[color]&=bitboard_clear[from]; board.rook_bitboard[color]|=bitboard_set[to]; board.piece[to]=piece_rook[color]; board.moves[from]++; break; // ... }?
-
Jetzt sind wir da, wo wir am Anfang waren

Mach dir doch einfach zwei Funktionen:
template<int Color> void make_move( int turn, int move ) { ... } void make_move( int color, int turn, int move ) { ... }Und miss jetzt endlich das Laufzeitverhalten

-
mache ich ja schon, bis später...

-
Nur so aus Interesse wuerde mich mal interessieren, warum du fuer schwarz anderen Code brauchst? Normalerweise kann ich doch ein zu einer gewissen Stellung, in der weiss am Zug ist, eine analoge Situation mit schwarz am Zug konstruieren, wo schwarz die gleichen Zugmoeglichkeiten bzw. Siegchancen hat. Die Zuege vor dieser Stellung interessieren fuer kaum eine Regel und sind dann auch symmetrisch - es ist also fast egal wie man zu der Stellung kommt. Also muesste dem Algorithmus die Seite eigentlich voellig egal sein. f'`8k
AutocogitoGruß, TGGC (Was Gamestar sagt...)
-
Ja es ist auch (fast) vollkommen egal. Lediglich die Reihen (bei Bauern - Doppelschritt oder Umwandlung) sowie die Rochadefelder sind unterschiedlich. Und bei den Bewertungen eben die Vorzeichen der Boni und Mali.
Mein Konzept war bisher möglichst speziellen Code schreiben, da dieser einfacher ist (und schneller??). Aber dadurch wird der Code redundanter.
Ergebnisse folgen in Kürze...
-
Tomahawk schrieb:
Lediglich die Reihen (bei Bauern - Doppelschritt oder Umwandlung) sowie die Rochadefelder sind unterschiedlich. Und bei den Bewertungen eben die Vorzeichen der Boni und Mali.
Ja, aber auch das ist voellig symmetrisch. Ich wuerde einfach eine KI fuer weiss schreiben, und wenn ich einen schwarzen Zug berechne, dann konstruiere ich die analoge weisse Position, loese diese und transformiere den Zug zurueck. f'`8k
Gruß, TGGC (Was Gamestar sagt...)