Source Code mit Nutzung con Com-Objejten deutlich langsmer im Thread

  • VB.NET
  • .NET (FX) 4.0

Es gibt 96 Antworten in diesem Thema. Der letzte Beitrag () ist von Tukuan.

    Source Code mit Nutzung con Com-Objejten deutlich langsmer im Thread

    Moin Forum-Nutzer,

    ich habe festgestellt, dass die Nutzung von einem Source Code Teil wesentlich langsamer (ca. 4 mal so lange) abläuft, wenn ich ihn in einem extra Thread gegenüber dem GUI-Thread laufen lasse. Hierbei ist es unwesentlich welche Priorität der Thread von bekommt.
    Da die Berechnungen aber recht lange dauern (immerhin ca. ca. 8 min im Hauptthread), würde die GUI die ganze Zeit stehen. Insgesammt habe ich aber nur 10 min Zeit, die Berechnung durchzuführen. Dann kommen die nächsten Daten, die berechnet werden wollen...

    Im Thread wird auf Com-Objekte zugegriffen. Das scheint so ein Problem zu sein...

    Im Internet bin ich auf folgendes gestoßen:
    Beim Umgang mit COM Objekten in .NET:
    ⇨ Geeignetes Threading Modell wählen.
    ⇨ Zwischen deterministischem und undeterministischem (GC) Löschen der Objekte wählen.
    ⇨ Nachrichten pumpen

    Leider verstehe ich die Aussagen nicht. Kann mir jemand helfen?

    Hier noch der Source Code zum Thread aufrufen:

    VB.NET-Quellcode

    1. CalcThread = New Thread(AddressOf MainStatisticCalculation)
    2. CalcThread.Priority = ThreadPriority.Highest
    3. CalcThread.Start()


    Vielen Danke schon mal im Voraus
    LG
    Tukuan

    Tukuan schrieb:

    Da die Berechnungen aber recht lange dauern
    Dann solltest Du sie parallelisieren mit Parallel.For oder Parallel.ForEach.
    Das bringt wesentlich mehr als ein schnöder Thread.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ja, leider... Ist eine externe Bibliothek.

    Es wird auch "nur" ein Thread gestartet, der dann einige Berechnungen ausführt. Bin mir noch nicht im Klaren, wie ich dass in Parallel.for verpacken kann.
    Es wird immer wieder auf einzelnen Ergebnisse zurückgegriffen und neue Berechnungen ausgeführt. Parallel ist da wohl schlecht möglich.

    Ich will ja im Prinzip nur nicht, dass die GUI die ganze Zeit hängt - UND das die Berechnung schnellstmöglich durchgeführt wird...

    Tukuan schrieb:

    Ja, leider... Ist eine externe Bibliothek.

    Ja ok, ich frage mich an solchen Stellen nur immer, ob es da nicht etwas anderes gibt.
    Du schreibst ja zum eigentlichen Programm/Thema/Prozess nichts, deswegen ist alles ein Rätselraten was Du da eigentlich berechnest.
    Hat denn der Anbieter dieser Bibliothek keine moderneren Produkte als COM Objekte?

    Tukuan schrieb:

    UND
    In einem separaten Thread machst Du Parallel.For. Ein zweiter Thread allein macht das Programm nicht schneller, sondern ausschließlich Parallelisierung.
    Was berechnest Du da genau?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Die com Schnittstell ist von imc und laut denen gibt es nichts neues. Aber deren neue Programme werden vermutlich nicht mehr mit der alten com Schnittstelle arbeiten. Sie haben somit bestimmt eine neue Bibliothek (API oder wie macht man sowas nun?). Aber das geben sie leider nicht raus.

    Es ist eine grob gesagt eine Mathematik-Bibliothek. Mit deren Hilfe wir Messdaten weiterverrechnen können.
    Im einfachsten Fall einfache Grundrechenarten mit Double-Arrays. Aber auch RMS und Mittelwertbildung, Trigometrische Funktionen, FFT und Filterfunktionen, und noch einiges mehr. Hinzu kommen Reportfunktionen, mit derem Hilfe z.B. Diagramme als Bilder abgespeichert werden können, und Komponenten diese Diagramm im eigenen Program darstellen zu lassen.

    In diesem Fall handelt es sich um eine FFT-Analyse die regelmäßig durchgeführt werden soll. Die Ergebnisse müssen dann sortiert und bewertet werden.

    Hab noch mal drüber nachgedacht. Könnte doch gehen...
    Aus der FFT bekomme ich zwei double-Arrays. Die mässte ich in ein anderes Double Array speichern, um daraus dann Min und Max-Werte usw. zu berechnen.
    Gibt es denn ein Tutorial, dass das parallel.for ein wenig genauer beschreibt?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Tukuan“ ()

    Tukuan schrieb:

    parallel.for
    Gugst Du hier.
    Immer zuerst die MSDN befragen. :thumbup:
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Tukuan schrieb:

    Die Ergebnisse werden als Dateien gespeichert.
    Das dauert auch eine ganze Weile. Wie sieht da Dein Code aus?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Tukuan schrieb:

    umzusetzen
    OK, ich würde da auch keinen Lambda-Ausdruck reinschreiben, sondern das in eine separate Prozedur packen, die kannst Du solo aufrufen und testen.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    simpelSoft schrieb:

    Die Schnittstelle ist ja von 2008 - unglaublich - schlafen die?

    Ja, tun sie wohl. Tief und fest. Aber sie werden wohl was neues haben, worauf ihre aktuellen Programme basieren. Geben sie nur nicht raus :(

    Ich habe mal versucht, den Source Code zu vereinfachen, damit er besser lesbar ist. Bekomme es aber nicht so schnell und einfach hin. Werde mich mal ans Parallelisieren machen.
    Kann man Parallel.For Schleifen auch verschachtelt?

    Kann mir einer dazu sonst noch was sagen:
    Beim Umgang mit COM Objekten in .NET:
    ⇨ Geeignetes Threading Modell wählen.
    ⇨ Zwischen deterministischem und undeterministischem (GC) Löschen der Objekte wählen.
    ⇨ Nachrichten pumpen

    Was bedeutet das?

    Was ist denn heute stand der Technik (statt com)?

    Tukuan schrieb:

    Kann man Parallel.For Schleifen auch verschachtelt?
    Nein.
    Wenn Du 5 ineinandergeschachtelte For-schleifen hast, solltest Du eine der äußeren beiden parallelisieren. Je weiter außen um so besser.
    Du musst den Code dann so umschreiben, dass innen nicht schreibend auf äußere Variablen zugegriffen wird!
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    OK. Danke.

    Wie schreibe ich die obere Funktion ohne lambda expression?

    VB.NET-Quellcode

    1. Private Sub MultiplyMatricesParallel(ByVal matA As Double(,), ByVal matB As Double(,), ByVal result As Double(,))
    2. Dim matACols As Integer = matA.GetLength(1)
    3. Dim matBCols As Integer = matB.GetLength(1)
    4. Dim matARows As Integer = matA.GetLength(0)
    5. ' A basic matrix multiplication.
    6. ' Parallelize the outer loop to partition the source array by rows.
    7. Parallel.For(0, matARows, Sub(i)
    8. For j As Integer = 0 To matBCols - 1
    9. ' Use a temporary to improve parallel performance.
    10. Dim temp As Double = 0
    11. For k As Integer = 0 To matACols - 1
    12. temp += matA(i, k) * matB(k, j)
    13. Next
    14. result(i, j) += temp
    15. Next
    16. End Sub)
    17. End Sub
    18. Private Sub MultiplyMatricesParallel2(ByVal matA As Double(,), ByVal matB As Double(,), ByVal result As Double(,))
    19. Dim matARows As Integer = matA.GetLength(0)
    20. ' A basic matrix multiplication.
    21. ' Parallelize the outer loop to partition the source array by rows.
    22. Parallel.For(0, matARows, AddressOf MultMatrix)
    23. 'So will er es nicht...
    24. 'Parallel.For(0, matARows, AddressOf MultMatrix(matA, matB, result))
    25. End Sub
    26. Sub MultMatrix(ByVal i As Integer) ', ByVal matA As Double(,), ByVal matB As Double(,), ByVal result As Double(,))
    27. Dim matACols As Integer = matA.GetLength(1)
    28. Dim matBCols As Integer = matB.GetLength(1)
    29. For j As Integer = 0 To matBCols - 1
    30. ' Use a temporary to improve parallel performance.
    31. Dim temp As Double = 0
    32. For k As Integer = 0 To matACols - 1
    33. temp += matA(i, k) * matB(k, j)
    34. Next
    35. result(i, j) += temp
    36. Next
    37. End Sub
    Das ist Unfug.
    Ich denke, herausgearbeitet ist inzwischen, dasses nicht der Gui-Zugriff ist, der laggt, sondern dass iwelche Daten auf Platte geschrieben werden.
    In deim gezeigten Code finden aber überhaupt keine Schreibzugriffe statt - wie gesagt: du suchst an der falschen Stelle.

    Bei Schreibzugriffen hilft kein Paralell.For mit Threads soviel wie Kernels da sind, sondern du brauchst genau einen Nebenthread, der die Schreibarbeit auf Platte übernimmt - denn es gibt nur eine Platte.

    Denkbar wäre eine Lösung mit einer BlockingCollection - die kann im einen Thread befüllt, und im anneren ausgelesen (und weggeschrieben) werden, ohne dass Komplikationen entstehen.

    Tukuan schrieb:

    ohne lambda expression?
    Ersetze die For-Schleifen durch eine Prozedur, wohin Du die schleifen rein packst und deren Namen an Stelle der Schleifen:

    VB.NET-Quellcode

    1. Parallel.For(0, matARows, Sub(i)
    2. MyProc(i)
    3. End Sub)
    4. '----------------
    5. Private Sub MyProc(i As Integer)
    6. For j As Integer = 0 To matBCols - 1
    7. ' Use a temporary to improve parallel performance.
    8. Dim temp As Double = 0
    9. For k As Integer = 0 To matACols - 1
    10. temp += matA(i, k) * matB(k, j)
    11. Next
    12. result(i, j) += temp
    13. Next
    14. End Sub
    (ungetestet)
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!