INFO: Dieses Forum nutzt Cookies...
Cookies sind für den Betrieb des Forums unverzichtbar. Mit der Nutzung des Forums erklärst Du dich damit einverstanden, dass wir Cookies verwenden.

Es wird in jedem Fall ein Cookie gesetzt um diesen Hinweis nicht mehr zu erhalten. Desweiteren setzen wir Google Adsense und Google Analytics ein.


Antwort schreiben 

DLL optimieren



Wenn dein Problem oder deine Frage geklärt worden ist, markiere den Beitrag als "Lösung",
indem du auf den "Lösung" Button rechts unter dem entsprechenden Beitrag klickst. Vielen Dank!

26.04.2009, 16:21
Beitrag #1

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
DLL optimieren
Folgende Problemstellung:
Ich habe ein Beispielcode des Herstellers einer Bibliothek genommen, in ein C++ Projekt gepackt und als exe kompiliert. Der Code arbeitet sauber und am wichtigsten sehr schnell. Danach kompiliere ich den gleichen Code als dll und der Code arbeitet immernoch sauber, aber um einiges langsamer. Ich weiß allerdings das es keinen unterschied in der Ausfürhungsgeschwindigkeit zwischen exe und dll geben dürfte. Wie kann ich also eine dll in der geschwindikeit optimieren. Ich arbeite mit VS 2008 und weiß das es bestimmte Compiler-Schalter gibt (auf Geschwindigkeit optimierter Code...), die aber allesamt versagen. Hat jemand ein ähnliches Problem lösen können, oder irgendwelche Ideen?

Danke, eure abrissbirne
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
27.04.2009, 08:01 (Dieser Beitrag wurde zuletzt bearbeitet: 27.04.2009 08:03 von rolfk.)
Beitrag #2

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
DLL optimieren
' schrieb:Folgende Problemstellung:
Ich habe ein Beispielcode des Herstellers einer Bibliothek genommen, in ein C++ Projekt gepackt und als exe kompiliert. Der Code arbeitet sauber und am wichtigsten sehr schnell. Danach kompiliere ich den gleichen Code als dll und der Code arbeitet immernoch sauber, aber um einiges langsamer. Ich weiß allerdings das es keinen unterschied in der Ausfürhungsgeschwindigkeit zwischen exe und dll geben dürfte. Wie kann ich also eine dll in der geschwindikeit optimieren. Ich arbeite mit VS 2008 und weiß das es bestimmte Compiler-Schalter gibt (auf Geschwindigkeit optimierter Code...), die aber allesamt versagen. Hat jemand ein ähnliches Problem lösen können, oder irgendwelche Ideen?

Danke, eure abrissbirne

Ohne den Code zu sehen lässt sich hier eigentlich gar nichts sagen. Das könnte an sehr viel Dingen liegen. Beispielsweise daran, dass ein C(++) Executable grundsätzlich single threaded ist, ausser Du machst Dir grosse Mühe im C Code selber.

Die DLL innerhalb von LabVIEW, läuft in einem Multithreaded System, da LabVIEW mit ziemlich vielen Threads aufgestartet wird. Wie wird denn die DLL Funktion aufgerufen? Innerhalb des UI Threads oder als Reentrant?

Wenn Du sie im UI Thread laufen lässt muss sich der DLL Code die CPU mit dem ganzen LabVIEW UI System teilen, der ausser zum Updaten des User Interfaces auch für allerlei Synchronisationsaufgaben zwischen verschiedenen beschützten Subsystemen verantwortlich ist.

Aber man kann nicht einfach eine Funktion reentrant konfigurieren wenn die nicht auch explizit dafür programmiert wurde. Dazu sollte sie grundsätzlich keinerlei globale Variablen ansprechen und auch nicht ohne Schutz (Semaphore oder ähnliches) auf externe Resourcen wie Hardwareschnittstellen etc zugreifen.

Aber selbst wenn Du die DLL korrekt reentrant ausführst wird sich der entsprechende Thread die CPU mit anderen Threads innerhalb von LabVIEW teilen müssen und wird wahrscheinlich ein wenig langsamer laufen als in einem single threaded Executable.

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
27.04.2009, 09:06
Beitrag #3

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
DLL optimieren
Ich habe den eigentlichen Quellcode in C++ Multithreaded programmiert. Maximal laufen bis zu drei Threads. Diese werden aber durch Semaphoren synchronisiert. Ich greife natürlich auch auf eine Hardware zu. Dafür habe ich Critical Sections verwandt um einen gleichzeitigen Zugriff zu vermeiden. Allerdings verwende ich schon globale Variablen die sich aber auch innerhalb der Critical Section befinden. Ist dies ausreichend um ein Skript als Threadsafe zu bezeichnen? Und sollte ich den reentrant Aufruf dann mal versuchen?

Danke für deine guten Antworten Rolf.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
27.04.2009, 09:48 (Dieser Beitrag wurde zuletzt bearbeitet: 27.04.2009 09:50 von rolfk.)
Beitrag #4

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
DLL optimieren
' schrieb:Ich habe den eigentlichen Quellcode in C++ Multithreaded programmiert. Maximal laufen bis zu drei Threads. Diese werden aber durch Semaphoren synchronisiert. Ich greife natürlich auch auf eine Hardware zu. Dafür habe ich Critical Sections verwandt um einen gleichzeitigen Zugriff zu vermeiden. Allerdings verwende ich schon globale Variablen die sich aber auch innerhalb der Critical Section befinden. Ist dies ausreichend um ein Skript als Threadsafe zu bezeichnen? Und sollte ich den reentrant Aufruf dann mal versuchen?

Danke für deine guten Antworten Rolf.

Solange alle globalen Resourcen (Hardware, globale Variablen, etc) innerhalb von Critical Sections geschützt sind sollte der Code als wiedereintrittsfähig (reentrant) gelten können. Ob das aber hilft mit der Performance ist eine andere Frage.

Critical Sections haben auch die Möglichkeit um Probleme zu verursachen, wie Priority inversion, interlocking, usw. Damit kann Code der grundsätzlich schnell läuft plötzlich sehr langsam laufen oder sich überhapt komplett blockieren und den entsprechenden Thread völlig aufhängen. Das hässliche dabei ist dass diese Problem sehr schwierig zu debuggen sind, da nicht immer genau und einfach reproduzierbar und im Moment wo Du im Locking zurecht kommst eigentlich auch nicht mehr debugbar sind, da der Debugger selber im Suspended Mode arbeiten können muss um Dir Dinge wie Single-Stepping und Source Code Level Debugging möglich zu machen.

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
29.04.2009, 16:22
Beitrag #5

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
DLL optimieren
So, ich habe meinen Übeltäter glaube ich ausfindig gemacht. Es liegt nicht an der DLL selbst, sondern an dem Quellcode. Den sollte ich optimieren. Ich denke das wird auch der häufigste Grund sein, wesshalb eine DLL nicht so schnell arbeitet.

Ich hoffe es stört niemanden wenn ich an dieser Stelle mein Problem weiter vertiefe.

Ich habe wie gesagt eine Datenaufnahme mit einer C-Bibliothek geschrieben. Das eigentliche Herzstück ist die Processingfunktion, welche die Daten aufnimmt. Dies soll in Echtzeit geschehen. Dazu werden Speicher mit Funktionen der Bibliothek reserviert. Ich dachte mir das folgendermaßen:
Nach jedem Schuss (der Datenaufnahme) wird eine Funktion aufgerufen. In dieser Funktion möchte ich die aufgenommenen Daten nur an LabVIEW weiterleiten. Dort werden die aufgenommenen Daten in eine Queue geschoben und weiterverarbeitet. Soweit funtkioniert das auch. Allerdings macht mir die Funktion, welche mir die Daten in ein LabVIEW Array kopiert, einen strich durch die Rechnung. Diese ist nämlich zu langsam. Ich kann mir allerdings die Adresse des Puffers auslesen, in welchen die Daten abgelegt wurden. Jetzt war mein zweiter Gedanke ich übergebe diesen Pointer einfach der Funktion PostLVUserEvent, aber das führt zu einem Fehler (unexpected exception oder so ähnlich). Nun habe ich versucht mittels des MoveBlock die Daten in mein LVPuffer zu schieben. Das funktioniert noch, aber wenn ich dann dies versuche:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>(*Memory)->dimSize[0] = 1234;
(*Memory)->dimSize[1] = 1234;</div>
um es mit dem PostLVUserEvent an LV zu übergeben kommt selbe Fehlermeldung wie eben geschildert. In etwa sieht das ganze so aus:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>typedef struct{
int32 dimSize[2];
uInt16 elements;
} **UInt16HAndle;

UInt16Handle LVMemory = NULL;

// Variable zum Speichern der Pufferadresse.
unsigned long addr;
GetBufferInfo(EventID, MODIFIED_BUFFER_ID, &Buffer);
BufferInquire(Buffer, HOST_ADDRESS, &addr);
MoveBlock((void*)addr, (void*)LVMemory, sizeof(uInt16)*SizeX*SizeY);
(*LVMemory)->dimSize[0] = SizeY;
(*LVMemory)->dimSize[1} = SizeX;

PostLVUserEvent(LVUserEventRef, &LVMemory);</div>
Wie kann ich im Letzten Schritt die Daten an mein LV Array übergeben und das möglichst schnell.

Danke (wahrscheinlich an Rolf ;-) )
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
29.04.2009, 16:37
Beitrag #6

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
DLL optimieren
' schrieb:So, ich habe meinen Übeltäter glaube ich ausfindig gemacht. Es liegt nicht an der DLL selbst, sondern an dem Quellcode. Den sollte ich optimieren. Ich denke das wird auch der häufigste Grund sein, wesshalb eine DLL nicht so schnell arbeitet.

Ich hoffe es stört niemanden wenn ich an dieser Stelle mein Problem weiter vertiefe.

Ich habe wie gesagt eine Datenaufnahme mit einer C-Bibliothek geschrieben. Das eigentliche Herzstück ist die Processingfunktion, welche die Daten aufnimmt. Dies soll in Echtzeit geschehen. Dazu werden Speicher mit Funktionen der Bibliothek reserviert. Ich dachte mir das folgendermaßen:
Nach jedem Schuss (der Datenaufnahme) wird eine Funktion aufgerufen. In dieser Funktion möchte ich die aufgenommenen Daten nur an LabVIEW weiterleiten. Dort werden die aufgenommenen Daten in eine Queue geschoben und weiterverarbeitet. Soweit funtkioniert das auch. Allerdings macht mir die Funktion, welche mir die Daten in ein LabVIEW Array kopiert, einen strich durch die Rechnung. Diese ist nämlich zu langsam. Ich kann mir allerdings die Adresse des Puffers auslesen, in welchen die Daten abgelegt wurden. Jetzt war mein zweiter Gedanke ich übergebe diesen Pointer einfach der Funktion PostLVUserEvent, aber das führt zu einem Fehler (unexpected exception oder so ähnlich). Nun habe ich versucht mittels des MoveBlock die Daten in mein LVPuffer zu schieben. Das funktioniert noch, aber wenn ich dann dies versuche:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>(*Memory)->dimSize[0] = 1234;
(*Memory)->dimSize[1] = 1234;</div>
um es mit dem PostLVUserEvent an LV zu übergeben kommt selbe Fehlermeldung wie eben geschildert. In etwa sieht das ganze so aus:
<div class='codetop'>CODE</div><div class='codemain' style='height:200px;white-space:pre;overflow:auto'>typedef struct{
int32 dimSize[2];
uInt16 elements;
} **UInt16HAndle;

UInt16Handle LVMemory = NULL;

// Variable zum Speichern der Pufferadresse.
unsigned long addr;
GetBufferInfo(EventID, MODIFIED_BUFFER_ID, &Buffer);
BufferInquire(Buffer, HOST_ADDRESS, &addr);
MoveBlock((void*)addr, (void*)LVMemory, sizeof(uInt16)*SizeX*SizeY);
(*LVMemory)->dimSize[0] = SizeY;
(*LVMemory)->dimSize[1} = SizeX;

PostLVUserEvent(LVUserEventRef, &LVMemory);</div>
Wie kann ich im Letzten Schritt die Daten an mein LV Array übergeben und das möglichst schnell.

Danke (wahrscheinlich an Rolf ;-) )

Also schau doch mal hier:

UInt16Handle LVMemory = NULL;

und dann hier:

MoveBlock((void*)addr, (void*)LVMemory, sizeof(uInt16)*SizeX*SizeY);

MoveBlock auf einen NULL pointer (Handle)? No

Da musst Du schon noch zuerst einen NumericArrayResize(uW, 2, &LVMemory, SizeX*SizeY); machen.

Und danach doch wirlklich bitte, bitte:

MoveBlock((void*)addr, (void*)(*LVMemory)->elements, sizeof(uInt16)*SizeX*SizeY);

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
29.04.2009, 17:08 (Dieser Beitrag wurde zuletzt bearbeitet: 29.04.2009 17:11 von abrissbirne.)
Beitrag #7

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
DLL optimieren
Warum kann ich eigenltich nicht mehr zitieren?

Egal, sorry, aber das NumericArrayResize hab ich natürlich in meinem Quellcode. Dies wied nur an einer anderen Stelle gemacht und ich hab vergessen es in diese Codebox zu kopieren. Das Thema hatten wir ja schonmal ;-) Also kein Nullhandle, aber ich hab vergessen auf (*LVMemory)->elemets zu dereferenzieren. Das werd ich morgen gleich mal testen.

Gibt es eventuell auch noch einen schnelleren Weg? Oder kann ich sogar den Pointer des Originalpuffers irgendwie verwenden? Ich allokiere den Puffer momentan auf der Aufnahmekarte, kann ihn aber auch woanders allokieren.

Danke^_^
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
29.04.2009, 19:01 (Dieser Beitrag wurde zuletzt bearbeitet: 29.04.2009 19:02 von jg.)
Beitrag #8

jg Offline
CLA & CLED
LVF-Team

Beiträge: 15.864
Registriert seit: Jun 2005

20xx / 8.x
1999
EN

Franken...
Deutschland
DLL optimieren
' schrieb:Warum kann ich eigenltich nicht mehr zitieren?
Offtopic2
Kannst du schon noch, bloß wird inzwischen aktive Mitarbeit vom Nutzer gefordert.
Einfach den Button "Zitieren" unter einem (oder mehreren) Beitrag(en) aktivieren, und dann erst auf "Antworten" gehen.
Hintergrund: Es wurde in letzter Zeit viel zu häufig grundlos zitiert durch den nicht mehr vorhandenen Antwort-Button direkt unter einem Beitrag. Das hat viele Threads schlecht lesbar und unnötig lang gemacht.
Gruß, Jens

Wer die erhabene Weisheit der Mathematik tadelt, nährt sich von Verwirrung. (Leonardo da Vinci)

!! BITTE !! stellt mir keine Fragen über PM, dafür ist das Forum da - andere haben vielleicht auch Interesse an der Antwort!

Einführende Links zu LabVIEW, s. GerdWs Signatur.
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
29.04.2009, 19:42
Beitrag #9

rolfk Offline
LVF-Guru
*****


Beiträge: 2.305
Registriert seit: Jun 2007

alle seit 6.0
1992
EN

2901GG
Niederlande
DLL optimieren
' schrieb:Gibt es eventuell auch noch einen schnelleren Weg? Oder kann ich sogar den Pointer des Originalpuffers irgendwie verwenden? Ich allokiere den Puffer momentan auf der Aufnahmekarte, kann ihn aber auch woanders allokieren.

Nun, wenn Du die Möglichkeit hast Deiner C Routine einen Pointer vom Heap zu übergeben dann ginge es. Dazu musst Du natürlich das Handle in der richtigen Grösse mit NumericArrayResize() allozieren und dann das (*LVMemory)->elements als Heappointer an Deine Libraryfunktion übergeben. Aber die Libraryfunktion muss natürlich als DLL von Dir aufgerufen werden und muss diesen Heappointer auch im Context der LabVIEW Applikation ansprechen. Das verlangt von der Library einiges and komplizierter Arbeit und deshalb wird das meist nicht unterstützt!

Ansonsten ist das kopieren der Daten unabwendbar. Die PostLVUserEvent() Funktion kann aus logischen Gründen nur mit LabVIEW native Datentypen arbeiten.

Rolf Kalbermatter

Rolf Kalbermatter
Technische Universität Delft, Dienst Elektronik und Mechanik
https://blog.kalbermatter.nl
Webseite des Benutzers besuchen Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
30.04.2009, 13:54 (Dieser Beitrag wurde zuletzt bearbeitet: 30.04.2009 14:00 von abrissbirne.)
Beitrag #10

abrissbirne Offline
LVF-Stammgast
***


Beiträge: 480
Registriert seit: Aug 2007

LV2009, LV2010
2007
EN

66123
Deutschland
DLL optimieren
' schrieb:Ansonsten ist das kopieren der Daten unabwendbar. Die PostLVUserEvent() Funktion kann aus logischen Gründen nur mit LabVIEW native Datentypen arbeiten.
Rolf Kalbermatter
Ok, danke dafür.
Es funktioniert zwar, ist aber auch nicht wesentlich schneller. Gibt es keine Möglichkeit einen Pointer auf Daten direkt an LV zu übergeben? Die Daten die aufgenommen werden haben den Datentyp Unsigned+16. Oder kann man sogar anstallt PostLVUserEvent Daten direkt in die LV Queu schieben.

Danke
Alle Beiträge dieses Benutzers finden
Diese Nachricht in einer Antwort zitieren to top
30
Antwort schreiben 


Gehe zu: