expertenaustausch > comp.lang.* > comp.lang.c

Moritz Franckenstein (26.02.2008, 21:17)
Hallo,

gibt es dafür in C eine Möglichkeit?

Wenn ich beides brauche, kann ich natürlich A/B und A%B machen, aber
dann wird die Division ja zweimal ausgeführt, und mir kommt es sehr auf
die Performance an.

Falls es da nichts vorgesehenes gibt, wird es ja sicher mit
eingebettetem Assembler gehen, oder? Leider kenne ich mich damit nicht aus.

Zusatzfrage: wie googelt man nach Fragen in Verbindung mit der Sprache C?
Rainer Weikusat (26.02.2008, 21:23)
Moritz Franckenstein <maf-soft> writes:
> gibt es dafür in C eine Möglichkeit?


div/ ldiv/ lldiv

Sebastian Biallas (26.02.2008, 21:45)
Moritz Franckenstein wrote:
> Hallo,
> gibt es dafür in C eine Möglichkeit?
> Wenn ich beides brauche, kann ich natürlich A/B und A%B machen, aber
> dann wird die Division ja zweimal ausgeführt,


Das kann passieren, muss aber nicht. Ein guter Compiler sollte das in
einer für die Zielplattform geeigneten Weise zusammenführen können.
Moritz Franckenstein (26.02.2008, 22:00)
Sebastian Biallas schrieb:
> Das kann passieren, muss aber nicht. Ein guter Compiler sollte das in
> einer für die Zielplattform geeigneten Weise zusammenführen können.


Naja, das wär schön, aber ich hätte jetzt gedacht das wäre etwas zu viel
erwartet... Ich verwende den Compiler im WINDDK.

Wie stelle ich sicher, maximale Performance zu bekommen?
Moritz Franckenstein (26.02.2008, 22:04)
Rainer Weikusat schrieb:
>> gibt es dafür in C eine Möglichkeit?

> div/ ldiv/ lldiv


Danke, tatsächlich so einfach...

Aber leiderleider kann man die stdlib.h in einem Treiber nicht verwenden:

error LNK2019: unresolved external symbol __imp__ldiv referenced

Nächster Vorschlag? :)
Moritz Franckenstein (26.02.2008, 22:42)
Sebastian Biallas schrieb:
>> Wenn ich beides brauche, kann ich natürlich A/B und A%B machen, aber
>> dann wird die Division ja zweimal ausgeführt

> Das kann passieren, muss aber nicht. Ein guter Compiler sollte das in
> einer für die Zielplattform geeigneten Weise zusammenführen können.


Es scheint, Du hast Recht - hier haben es einige Leute ausprobiert:



Ich hoffe nun einfach, dass das für meinen Compiler auch gilt.

Danke!
Thomas Richter (27.02.2008, 00:23)
Moritz Franckenstein wrote:
> Rainer Weikusat schrieb:
> Danke, tatsächlich so einfach...
> Aber leiderleider kann man die stdlib.h in einem Treiber nicht verwenden:
> error LNK2019: unresolved external symbol __imp__ldiv referenced
> Nächster Vorschlag? :)


Trau' Deinem Compiler. Das ist eine recht triviale Optimierung, jeder
halbwegs aktuelle Compiler sollte das auf die Reihe bekommen und die
zweite Division in's Nirvana optimieren, wenn die Zielarchitektur das in
einem Arbeitsgang anbietet. (Viele, aber nicht alle tun das).

Grüße,
Thomas
Stefan Ram (27.02.2008, 03:47)
Moritz Franckenstein <maf-soft> writes:
>Wie stelle ich sicher, maximale Performance zu bekommen?


Sebastian Biallas (27.02.2008, 03:54)
Stefan Ram wrote:
> Moritz Franckenstein <maf-soft> writes:
>> Wie stelle ich sicher, maximale Performance zu bekommen?

>


Das beantwortet seine Frage nicht, weil Du den Kontext, in dem er
gefragt hat, weggeschnitten hast.

Abgesehen davon beantwortet der verlinkte Artikel nicht mal die
generalisierte Frage.
Joachim Schmitz (27.02.2008, 10:22)
Moritz Franckenstein wrote:
> Rainer Weikusat schrieb:
> Danke, tatsächlich so einfach...
> Aber leiderleider kann man die stdlib.h in einem Treiber nicht
> verwenden:
> error LNK2019: unresolved external symbol __imp__ldiv referenced
> Nächster Vorschlag? :) Vermutlich hilft linken der mathe lib, üblicherweise via "-lm"


Tschö, Jojo
Rainer Weikusat (27.02.2008, 12:28)
Thomas Richter <thor> writes:
> Moritz Franckenstein wrote:
> Trau' Deinem Compiler. Das ist eine recht triviale Optimierung, jeder
> halbwegs aktuelle Compiler sollte das auf die Reihe bekommen und die
> zweite Division in's Nirvana optimieren,


In dieser Form ist das eine recht sinnfreie Spekulation. Ob ein
Compiler eine solche Optimierung 'automatisch' vornimmt, haengt
letztendlich davon ab, wie der Quellcode aussieht, mit dem er
gefuettert wurde, dh zum Beispiel, ob die Moeglichkeit einer solchen
Ersetzung ueberhaupt erkannt wird, ob die 'execution ressources' (zB
freie Register) um Zwischenwerte aufzuheben, zur Verfuegung stehen
usf. Man muss das also, wenn man es fuer wichtig haelt, fuer jede
Kombination von Compiler, Compiler-Version, Zielplattform und
Quellcode, die relevant sein koennte, einzeln experimentell ermitteln
(Code uebersetzen lassen und schauen, was dabei herauskommt). Das ist
potentiell eine Menge Arbeit, die man sich eigentlich sparen koennen
sollte. ZB dadurch, dass man einem Compiler mehr Informationen ueber
den 'Sinn' einer Operation zukommen laesst anstatt sie darauf zu
verlassen, dass er ihn schon wird erraten koennen. Also zB explizit
eine der genannten Routinen verwendet, falls man zum Zeitpunkt der
Division bereits weiss, dass man sowohl das Ergebnis als auch den Rest
benoetigen wird.

Im uebrigen sollte das lauten 'verlasse Dich vorbehaltlos darauf, dass
diejenigen, die den Compiler entwickeln/ entwickelt haben nicht nur
dieselben Ansichten bezueglich wuenschenswerter tradeoffs hatten, wie
Du, sondern ausserdem auch einen immer funktionieren Algorithms
gekannt haben, der diese verwirklicht und diesen in jedem Fall
fehlerfrei implementiert haben'.

Die (meine) praktische Erfahrung ist allerdings eher 'Wer sich auf
andere verlaesst, ist verlassen'.

YMMV.
Moritz Franckenstein (27.02.2008, 12:59)
Thomas Richter schrieb:
> Trau' Deinem Compiler. Das ist eine recht triviale Optimierung, jeder
> halbwegs aktuelle Compiler sollte das auf die Reihe bekommen und die
> zweite Division in's Nirvana optimieren, wenn die Zielarchitektur das in
> einem Arbeitsgang anbietet. (Viele, aber nicht alle tun das).


Ja, das habe ich nun auch getan. Leider fehlen mir die Tools und das
Wissen, um zu prüfen ob es geklappt hat. Naja.
Thomas Richter (27.02.2008, 13:08)
Moritz Franckenstein wrote:
> Thomas Richter schrieb:
> Ja, das habe ich nun auch getan. Leider fehlen mir die Tools und das
> Wissen, um zu prüfen ob es geklappt hat. Naja.


Schau, die Tools, die Du versuchen solltest, sind ein Profiler und/oder
ein Debugger. Ich würde nicht weiter an einem Problem herumdoktoren,
welches kein Problem ist. Wenn der Code für Deine Zwecke schnell und
effizient genug ist, lass' es dabei. Wenn Du den Verdacht hast, dass
*nur aufgrund dieses* Codes das Programm Deine Anforderungen nicht
erfüllt, würde ich weiter suchen, vielleicht mit einem Disassembler.

Grüße,
Thomas
Moritz Franckenstein (27.02.2008, 13:10)
Rainer Weikusat schrieb:
> fuer jede Kombination von Compiler, Compiler-Version, Zielplattform
> und Quellcode, die relevant sein koennte, einzeln experimentell
> ermitteln (Code uebersetzen lassen und schauen, was dabei
> herauskommt). Das ist potentiell eine Menge Arbeit, die man sich
> eigentlich sparen koennen sollte. ZB dadurch, dass man einem Compiler
> mehr Informationen ueber den 'Sinn' einer Operation zukommen laesst
> anstatt sie darauf zu verlassen, dass er ihn schon wird erraten
> koennen. Also zB explizit eine der genannten Routinen verwendet,
> falls man zum Zeitpunkt der Division bereits weiss, dass man sowohl
> das Ergebnis als auch den Rest benoetigen wird.


Dem Compiler mehr Informationen geben, ja, das wär schön, aber durch
einen Funktionsaufruf? Der hat doch wieder unnötigen Overhead. Und die
Umkopiererei in den Datenrecord ist eigentlich auch unnötig.

Dann würde ich doch eher sagen, inline-assembler - Zielplattformen habe
ich sowieso nur 2.

Aber am Besten ist sicherlich, wenn die Compiler-Optimierung so klappt
wie in dem Thread-Link, den ich schon gepostet habe.
Rainer Weikusat (27.02.2008, 13:53)
Moritz Franckenstein <maf-soft> writes:
> Rainer Weikusat schrieb:
> Dem Compiler mehr Informationen geben, ja, das wär schön, aber durch
> einen Funktionsaufruf? Der hat doch wieder unnötigen Overhead.


Wenn Du wissen moechtest, wie sich das verhaelt, weil Du nicht glauben
moechtest, dass es sich so verhaelt, wie jemand anderer gesagt hatte,
dass es dass tun wuerde, dann musst Du aufhoeren, rumzuraten, und das
stattdessen fuer den Code, der Dich interessiert, ausprobieren.

Ein paar Beispiel: gcc 4.1.1 mit stdlib-div benutzt fuer x86 die
entsprechende Instruktion fuer 'manuelle Division' und macht einen
libc-call fuer div. Eine triviale inline-Definition fuer div fuehrt
dazu, dass in beiden Fallen derselbe Code generiert wird. gcc 3.2.2
fuer ARM9 ruft fuer Divisionen einen Bibliotheksroutine auf, die zwei
SWI(software interrupt)-Instruktionen pro Division aussfuehrt (dh eine
kernel-routine aufruft). Fuer div wird diese Funktion einmal
ausgefuehrt, fuer 'manuelle Division' zweimal.

Fazit: Falls diejenigen, die Deine C-Standardbibliothek implementiert
haben, es der Muehe fuer wert befunden haben, eine sinnvolle
div-Implementierung fuer eine bestimmte Plattform zur Verfuegung zu
stellen, kannst Du davon ausgehen, dass diese schlimmstenfalls
aequivalent zu der manuellen Division ist und potentiell erheblich
billiger. Ob sie das getan haben, kann man herausfinden. Ggf koennte
man das auch als 'bug report' irgendwohin senden.

Aber wenn ich mich nicht stark irre, habe ich genau das schon einmal
geschrieben und im uebrigen ist dieser ganze Quark, insofern er ueber
den allgemeinen Ratschlag hinausgeht, sinnvoll einsetzbare
Bibliotheksroutinen auch tatsaechlich zu benutzen, anstatt aufgrund
irgendwelcher Vermutungen lieber alles selber zu kodieren, vollkommen
off topic.

Ähnliche Themen