Template Funktionen versus Inline Funktionen
-
Ganz einfache Frage
Kann ich beim Einsatz von Inline-Funktionen (global innerhalb einer Headerdatei) auf Templates verzichten?
Beispiel a.h
#ifndef A_H #define A_H inline int foo(int a, int b) { return v[a][b]; } template<int A, int B> inline int foo_t() { return v[A][B]; } #endifIch denke schon, dass der Einsatz eines Templates ala foo_t() unsinnig ist, da die Inline-Funktion an der Stelle des Aufrufs expandiert wird. Somit wäre die Performance identisch!?
Stimmt das so?
-
Warum machst du da überhaupt ein template hin?!
Performance mässig wird das schon einen Unterschied machen, aber das kommt daher, dass beim foo_t die Parameter nicht variable (zur Laufzeit) sind und somit kann das sicher einfacher umgesetzt werden.
Aber eine solche Performance Überlegung ist hier unsinnig.
-
drakon schrieb:
Warum machst du da überhaupt ein template hin?!
Performance mässig wird das schon einen Unterschied machen, aber das kommt daher, dass beim foo_t die Parameter nicht variable (zur Laufzeit) sind und somit kann das sicher einfacher umgesetzt werden.
Aber eine solche Performance Überlegung ist hier unsinnig.
Naja, das ist nicht unbedingt unsinnig, sondern soll nur ein einfaches kontextfreies Beispiel sein. Man überlege, eine Engine bestehe aus einigen Template-Funktionen, deren Funktionalität darin bestehe, ihre Aufgaben auf kleine Inline Funktionen zu verteilen. Dann stehen die "Übergabeparameter" bereits zur Compilezeit fest und der Einsatz von zusätzlichen Inline-Funktionstemplates ist überflüssig.
Sorry, habe die Problematik ungenau beschrieben.
-
Naja - selbst, wenn es zur Compilezeit bekannt ist, würde ich kein template aus so ner Fkt machen...
Erstens kann der Compiler dann auch so optimieren, wenn er das für nötig hält (und du ihn lässt) und 2. macht das vll pro aufruf 2 Takte aus... wär mir zu wenig, um dafür so was hässliches zu bauen...bb
-
2 Takte?
2 Takte sind geboten.
Höre ich 3?
Wer bietet 3 Takte?
2 Takte zum 1, 2 Takte zum 2, verkauft...Die inline-Funktion wurde für zusätzliche 2 Takte an den unfähigen Typen verkauft...
-
@Tomahawk:
Guck einfach was der Compiler für Code draus macht. In einem Release-Build mit eingeschalteten Optimierungen sollte das gleiche rauskommen.
-
hustbaer schrieb:
@Tomahawk:
Guck einfach was der Compiler für Code draus macht. In einem Release-Build mit eingeschalteten Optimierungen sollte das gleiche rauskommen.Hmm. Ich denke, dass da minimal was kürzeres rauskommt bei der template Version, weil ja die Parameter nicht dynamisch sind. Ich hätte mal so gesagt, dass irgendwie eine Inderektion weniger raus kommt.
-
drakon schrieb:
hustbaer schrieb:
@Tomahawk:
Guck einfach was der Compiler für Code draus macht. In einem Release-Build mit eingeschalteten Optimierungen sollte das gleiche rauskommen.Hmm. Ich denke, dass da minimal was kürzeres rauskommt bei der template Version, weil ja die Parameter nicht dynamisch sind. Ich hätte mal so gesagt, dass irgendwie eine Inderektion weniger raus kommt.
ich denke, er wird eine multiplikation und eine addition sparen - aber so ganz sicher kann man sich erst sein, wenn man es mal ausprobiert hat - hatte ja auch die ganze zeit schon gehofft, dass es jmd ausprobiert, da ich selbst zu faul bin : D
bb
-
Äh.
Ich gehe selbstverständlich von einen fairen und sinnvollen Vergleich aus.
D.h. beide Funktionen müssen gleich aufgerufen werden.Da die Template Funktion nur mit Konstanten funktioniert muss natürlich die inline Funktion auch mit Konstanten aufgerufen werden.
Der Code der dabei dann rauskomme sollte dann besser der gleiche sein, sonst würde ich mich um einen neuen Compiler umsehen.
-
unskilled schrieb:
drakon schrieb:
hustbaer schrieb:
@Tomahawk:
Guck einfach was der Compiler für Code draus macht. In einem Release-Build mit eingeschalteten Optimierungen sollte das gleiche rauskommen.Hmm. Ich denke, dass da minimal was kürzeres rauskommt bei der template Version, weil ja die Parameter nicht dynamisch sind. Ich hätte mal so gesagt, dass irgendwie eine Inderektion weniger raus kommt.
ich denke, er wird eine multiplikation und eine addition sparen - aber so ganz sicher kann man sich erst sein, wenn man es mal ausprobiert hat - hatte ja auch die ganze zeit schon gehofft, dass es jmd ausprobiert, da ich selbst zu faul bin : D
bb
Aber - wie schon erwähnt - wird der Compiler wahrscheinlich in beiden Versionen denselben Code generieren - ohne Indirektionen. Weil die Inline Funktionen von Template-Funktionen aufgerufen werden (sind nur vereinfachte "sinnlose" Beispiele).
// a.h #ifndef A_H #define A_H inline int foo(int x, int y) { return v[a][b]; } #endif // b.h #ifndef B_H #define B_H extern int func_b(int z); #endif // b.cpp #include "a.h" #include "b.h" namespace { template<int X, int Y> int temp_b() { return foo(X, Y); } } int func_b(int z) { return (z == 0) ? temp_b<27, 8>() : temp_b<7, 13>; }
-
hustbaer schrieb:
Äh.
Ich gehe selbstverständlich von einen fairen und sinnvollen Vergleich aus.
D.h. beide Funktionen müssen gleich aufgerufen werden.Da die Template Funktion nur mit Konstanten funktioniert muss natürlich die inline Funktion auch mit Konstanten aufgerufen werden.
Der Code der dabei dann rauskomme sollte dann besser der gleiche sein, sonst würde ich mich um einen neuen Compiler umsehen.
Jep, so sollte es logischerweise sein!
-
Tomahawk schrieb:
Kann ich beim Einsatz von Inline-Funktionen (global innerhalb einer Headerdatei) auf Templates verzichten?
Darf ich hier mal Gegenfragen, ob du die Frage wirklich so allgemein verstehst oder ob du es wirklich nur auf solche Funktionen reduzieren willst, wie du sie hier als Beispiele präsentierst? Also nur Funktionstemplates von diesem einen speziellen Typen? Will nur sicher gehen

Grüssli
-
[quote="drakon"]
hustbaer schrieb:
Hmm. Ich denke, dass da minimal was kürzeres rauskommt bei der template Version, weil ja die Parameter nicht dynamisch sind. Ich hätte mal so gesagt, dass irgendwie eine Inderektion weniger raus kommt.
Das hängt davon ab, ob er der Funktion Konstanten übergibt oder nicht. Sonst kann der Compiler da natürlich auch optimieren. Alles in allem aber eine ziemlich unnötige Überlegung hier.
-
Tomahawk, du solltest Nicht-Template-Funktionen soweit möglich in .cpp-Dateien definieren. Somit ersparst du dir unnötige Abhängigkeiten und reduzierst die Kompilierzeit. Wenn du Templates brauchst, nimmst du Templates. Aber mach dir nicht zu viele unnötige Gedanken um die Performance, sonst wird deine Schach-Engine niemals fertig. Ich denke nicht, dass du am Schluss wegen Funktionsaufrufen in Schwierigkeiten kommst, da wirst du genügend andere Probleme haben. Viel wichtiger ist es, auf sauberen Code und eine gute Kapselung zu achten, das erleichtert spätere Optimierungen nämlich enorm.
FrEEzE2046 schrieb:
Das hängt davon ab, ob er der Funktion Konstanten übergibt oder nicht. Sonst kann der Compiler da natürlich auch optimieren. Alles in allem aber eine ziemlich unnötige Überlegung hier.
Stimmt, die Wiederholung von bereits Gesagtem ist hingegen viel nötiger hier. :p
-
Nexus schrieb:
Tomahawk, du solltest Nicht-Template-Funktionen soweit möglich in .cpp-Dateien definieren. Somit ersparst du dir unnötige Abhängigkeiten und reduzierst die Kompilierzeit. Wenn du Templates brauchst, nimmst du Templates. Aber mach dir nicht zu viele unnötige Gedanken um die Performance, sonst wird deine Schach-Engine niemals fertig. Ich denke nicht, dass du am Schluss wegen Funktionsaufrufen in Schwierigkeiten kommst, da wirst du genügend andere Probleme haben. Viel wichtiger ist es, auf sauberen Code und eine gute Kapselung zu achten, das erleichtert spätere Optimierungen nämlich enorm.
Hi

Würde auch nie eine Template-Funktion einsetzten, wenn diese keine messbare Zeitersparnis bringt. Die Kompilierzeit ist eher zweitrangig, da (1) das Komplieren immer sehr lange dauert wegen PGO mittels Traingsdatensatz und (2) der neue Beta Compiler aus VC2010 (noch Beta?) alle Rechenkerne beim Compilieren nutzen kann.Und tatsächlich, du hast vollkommen recht, schneller sauberer Code ist schnellerem unsauberen Code immer vorzuziehen. Daher suche ich stets den "gesunden Kompromiss"

-
schon ewigkeiten nicht mehr beta!

vor ca. 2 wochen war release^^
msdnaa sei dank, hab ich ihn auch schon - nur war ich zu faul zum probieren - von der beta war ich das letzte mal so extrem enttäuscht..es gab davor btw auch tools, womit alle kerne beim kompilieren genutzt wurden...
bb
-
Tomahawk schrieb:
Würde auch nie eine Template-Funktion einsetzten, wenn diese keine messbare Zeitersparnis bringt.
Warum das? Abstraktionsmittel verwendet man primär zur Abstraktion und nicht zur Performancesteigerung. Nutze die Sprachfeatures, wenn sie Sinn machen.
Vielleicht hast du meinen Post falsch verstanden. Ich wollte keineswegs darauf hinaus, dass du Templates meiden solltest. Jedoch sollte Performance nicht das einzige Kriterium sein – ob für oder gegen ihren Einsatz. Ich selbst benutze oft Templates, da sie ein wahnsinnig mächtiges Sprachmittel sind.
-
@Nexus:
Man kann Templates wunderbar dafür verwenden etwas auf Performance zu optimieren.
Beispiel statischer polymorphismus (hatten wir erst kürzlich nen Beitrag zu dem Thema).
Und ich finde das auch nicht verkehrt/schlecht/pöse.Wobei ich allerdings in einem Beispiel wie diesem KEIN Template verwenden würde, da es keinen Sinn macht (weil dadurch auch nix schneller wird).
-
hustbaer schrieb:
@Nexus:
Man kann Templates wunderbar dafür verwenden etwas auf Performance zu optimieren.Ja, aber eben nicht primär. Meiner Meinung nach werden Templates hauptsächlich der Abstraktion wegen eingesetzt. Spielt natürlich auch eine Rolle, wie zeitkritisch das Projekt gerade ist, an dem man arbeitet. Je nachdem kann es schon sinnvoll sein, z.B. dynamische durch statische Polymorphie zu ersetzen, oder mit Metaprogrammierung bereits Berechnungen zur Kompilierzeit auszuführen.
Aber da Tomahawk in letzter Zeit mit seiner Schach-Engine stark in Richtung Premature Optimization tendiert, ist es für ihn sicher gut zu wissen, dass Templates mehr können als nur optimieren.

-
Nexus schrieb:
hustbaer schrieb:
@Nexus:
Man kann Templates wunderbar dafür verwenden etwas auf Performance zu optimieren.Ja, aber eben nicht primär. Meiner Meinung nach werden Templates hauptsächlich der Abstraktion wegen eingesetzt. Spielt natürlich auch eine Rolle, wie zeitkritisch das Projekt gerade ist, an dem man arbeitet. Je nachdem kann es schon sinnvoll sein, z.B. dynamische durch statische Polymorphie zu ersetzen, oder mit Metaprogrammierung bereits Berechnungen zur Kompilierzeit auszuführen.
Aber da Tomahawk in letzter Zeit mit seiner Schach-Engine stark in Richtung Premature Optimization tendiert, ist es für ihn sicher gut zu wissen, dass Templates mehr können als nur optimieren.

Natürlich sind Templates nur dazu da "zu optimieren". Was tut man denn mit Templates? Die Übersichtlichkeit und Wartbarkeit des Codes wird optimiert. Redundante Strukturen automatisch ersetzt oder Berechnungen zu Kompilezeit ausgeführt. Indirektionen verringert, parametrisiert, ...
Zum Projekt Schachengine
Premature Optimization wäre es in einem früheren Stadium gewesen. Jetzt geht es ganz klar darum
1. die Knotenleistung (=Performance) parallel mit
2. der Selektivität der Suche,
3. dem Zeitmanagement in Partien und
4. dem Schachwissen (Midgame+Endgame)zu optimieren. Wobei 1. der einzige deterministische Bereich ist, der keinen Trade-Off hat. 2-4 sind immer nur Kompromisse. Wird zB an 2. gearbeitet, bedeutet ist das ein Trade-Off Präzision vs. Spekulation.
Für die anderen Bereiche gibt es andere Foren. Für 1. kann ich mir hier ein paar Anregungen holen

Und ja, mir sind schon einige Prinzipien der Abstraktion klar, aber hat das auch wirklich immer einen Sinn?
Beispiel Objekte
Weshalb soll ich bei jedem Funktionsaufruf implizit einen this-Zeiger mitschicken oder beim Bearbeiten jeder Membervariablen eine implizite Dereferenzierung machen, wenn das ganze viel günstiger mit einem Struct und einem globalen Objekt zu realisieren ist?
Und dadurch wird nichts "unsicherer" oder "weniger abstrakt", man muss eben nur sorgfältig abwägen.
