26.04.2009, 16:21
Beitrag #1
|
|
|
27.04.2009, 08:01
(Dieser Beitrag wurde zuletzt bearbeitet: 27.04.2009 08:03 von rolfk.)
Beitrag #2
|
rolfk
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
|
|
|
27.04.2009, 09:06
Beitrag #3
|
|
|
29.04.2009, 16:22
Beitrag #5
|
abrissbirne
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 ;-) )
|
|
|
29.04.2009, 16:37
Beitrag #6
|
rolfk
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)?
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
|
|
|
29.04.2009, 17:08
(Dieser Beitrag wurde zuletzt bearbeitet: 29.04.2009 17:11 von abrissbirne.)
Beitrag #7
|
|
|
29.04.2009, 19:01
(Dieser Beitrag wurde zuletzt bearbeitet: 29.04.2009 19:02 von jg.)
Beitrag #8
|
jg
CLA & CLED
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?
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.
|
|
|
30.04.2009, 13:54
(Dieser Beitrag wurde zuletzt bearbeitet: 30.04.2009 14:00 von abrissbirne.)
|
abrissbirne
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
|
|
|
| |