Threads
-
Hallo,
ich habe ein kleines Problem.Ich habe 2 Threads mit CreateThread instanziert.
Thread 1: Sucht bestimmte Dateien auf einem Medium
Thread 2: Verarbeitet die bestimmten DateienJetzt ist der Thread 1 sehr viel schneller als der Thread 2. Wie erreiche ich es, dass eine Art "Leitung" gelegt wird? Also Thread 1 schreibt durchgehend alles in einen Queue und Thread 2 holt sich die Daten aus dem Queue heraus und verarbeitet sie.
Vieleicht ist das auch ehr eine API frage aber wie kann ich sowas realisieren?
-
Hi,
ich kann dir mal meine Queue die ich in C geschiebn hab zeigen. Vielleicht hilft dir das ja ein bissle weiter:
/* queue.h */ #ifndef __QUEUE__ #define __QUEUE__ #include <windows.h> typedef struct queue_item { void* pContent; struct queue_item* pNext; }QUEUE_ITEM, *PQUEUE_ITEM; typedef struct queue { PQUEUE_ITEM pQueueFirst; PQUEUE_ITEM pQueueLast; unsigned int uiItems; CRITICAL_SECTION CritSection; }QUEUE,* PQUEUE; void AddToQueue(PQUEUE pQueue, void* pToAdd); void* RemoveFromQueue(PQUEUE pQueue); unsigned int GetItemCount(PQUEUE pQueue); void FreeQueue(PQUEUE pQueue); #endif
/* queue.c */ #include <windows.h> #include <stdlib.h> #include "Queue.h" void AddToQueue(PQUEUE pQueue, void* pToAdd) { PQUEUE_ITEM pTmp = malloc(sizeof(QUEUE_ITEM)); if(pTmp) { pTmp->pNext = NULL; pTmp->pContent = pToAdd; EnterCriticalSection(&pQueue->CritSection); if(pQueue->pQueueLast != NULL) { pQueue->pQueueLast->pNext = pTmp; pQueue->pQueueLast = pQueue->pQueueLast->pNext; } else { pQueue->pQueueLast = pTmp; pQueue->pQueueFirst = pTmp; } pQueue->uiItems++; LeaveCriticalSection(&pQueue->CritSection); } } void* RemoveFromQueue(PQUEUE pQueue) { PQUEUE_ITEM pTmp = pQueue->pQueueFirst; void* pTmpContent = NULL; if(pTmp) { EnterCriticalSection(&pQueue->CritSection); if(pQueue->pQueueFirst == pQueue->pQueueLast) { pQueue->pQueueFirst = NULL; pQueue->pQueueLast = NULL; } else pQueue->pQueueFirst = pQueue->pQueueFirst->pNext; pQueue->uiItems--; LeaveCriticalSection(&pQueue->CritSection); pTmpContent = pTmp->pContent; free(pTmp); } return pTmpContent; } unsigned int GetItemCount(PQUEUE pQueue) { unsigned int uiTmp; /* ob hier ne critical section noetig is weiss ich nicht genau */ EnterCriticalSection(&pQueue->CritSection); uiTmp = pQueue->uiItems; LeaveCriticalSection(&pQueue->CritSection); return uiTmp; } void FreeQueue(PQUEUE pQueue) { PQUEUE_ITEM pTmp; while(pQueue->pQueueFirst) { pTmp = pQueue->pQueueFirst; pQueue->pQueueFirst = pTmp->pNext; free(pTmp->pContent); free(pTmp); } pQueue->pQueueFirst = NULL; pQueue->pQueueLast = NULL; }
Diese ist Thread Save (wuerd ich zumindestens behaupten) somit kannst du immer Dateien in die Queue hinzufuegen und im 2. Thread die Daten dann wieder holen und mit ihnen arbeiten.
Peace & Blessed Love C0de4Fun
PS: Und vor dem benutzen natuerlich die CriticalSection mit "InitializeCriticalSection" initializieren
-
Alternative: Pipe nehmen aus der API.
-
Dieser Thread wurde von Moderator/in Nobuo T aus dem Forum Assembler in das Forum Rund um die Programmierung verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
secondsun schrieb:
Wie erreiche ich es, dass eine Art "Leitung" gelegt wird? Also Thread 1 schreibt durchgehend alles in einen Queue und Thread 2 holt sich die Daten aus dem Queue heraus und verarbeitet sie.
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
Jetzt ist der Thread 1 sehr viel schneller als der Thread 2.
in dem fall solltest du dir ueberlegen, ob du nicht lieber beide threads die dateien verarbeiten laesst, ansonsten ist das langsammer als es sein koennte.
-
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
rapso schrieb:
Jetzt ist der Thread 1 sehr viel schneller als der Thread 2.
in dem fall solltest du dir ueberlegen, ob du nicht lieber beide threads die dateien verarbeiten laesst, ansonsten ist das langsammer als es sein koennte.
oder nur einen thread nehmen, der suchen und verarbeiten nacheinander macht.
-
Beides in einem Thread ist natürlich Käse, weil I/O langsam ist und somit der Such-Thread ständig auf Daten warten muss in welcher Zeit Thread2 munter die Daten verarbeiten kann.
Falls es wen interessiert: A lockless ring-buffer
-
Kenner der Wahrheit schrieb:
Falls es wen interessiert: A lockless ring-buffer
das gibts auch noch: http://www.koders.com/c/fidA649E1A0EA070488C13F29677B14D7C09E3E0187.aspx
-
Hey,
schön das hier so viele konstruktive Antworten kommen:-) Finde ich super.
Mich würde das mit den Pipes aus der API32(?) interessieren da das andere meinen Horizont übersteigt:-PDeswegen würde ich gerne wissen wie das mit den Pipes funktioniert. Hat das jemand schon mal gemacht und welche Funktionen stehen mir zur Verfügung. Wenn sich keiner damit auskennt, dann muss ich mich wohl mit den anderen Sachen auseinander setzen;-)
-
Die Pipe erzeugst DU mit CreatePipe http://msdn.microsoft.com/en-us/library/aa365152(VS.85).aspx und kannst dann mit WriteFile reinschreiben und im anderen Thread mit ReadFile rauslesen. Ich würde vermutlich nichtmal die Daten selber pipen, sondern die Daten immer mit new anlegen und nur Zeiger drauf pipen.
-
das geht jetzt nicht gegen irgendwen bestimmten...
glaubt ihr dass der OP auch nur den funken einer chance hat, eure tollen lock-free ring-buffer hier zu verstehen, oder gar fehlerfrei zu implementieren? mal davon abgesehen dass es IMO total plem ist mit lock-free algorithmen auf was draufzuhauen was IO-limitiert ist.
eine stinknormale queue, sowas in der art wie C0de4Fun gepostet hat, ist hier sicher das beste.
-
;fricky schrieb:
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
doch, normalerweise ist das der fall. man muss sich schon muehe geben sowas simples kaputt zu implementieren.
rapso schrieb:
Jetzt ist der Thread 1 sehr viel schneller als der Thread 2.
in dem fall solltest du dir ueberlegen, ob du nicht lieber beide threads die dateien verarbeiten laesst, ansonsten ist das langsammer als es sein koennte.
oder nur einen thread nehmen, der suchen und verarbeiten nacheinander macht.
einen thread zu nutzen statt die arbeit auf zwei aufzuteilen soll welchen vorteil genau bringen?
-
hustbaer schrieb:
glaubt ihr dass der OP auch nur den funken einer chance hat, eure tollen lock-free ring-buffer hier zu verstehen, oder gar fehlerfrei zu implementieren?
ein ringbuffer der nur einen feeder und nur einen consumer hat ist in den allermeisten implementierungen lock-/waitfree. da muss man nichts an hyper funky dingen imlementieren.
mal davon abgesehen dass es IMO total plem ist mit lock-free algorithmen auf was draufzuhauen was IO-limitiert ist.
er sagte der IO thread ist sehr viel schneller.
weiter hat lockfree und IO limitierung nichts miteinander zu tun.eine stinknormale queue, sowas in der art wie C0de4Fun gepostet hat, ist hier sicher das beste.
ja, wenn man spatzen mit raketenwerfen ausschalten will.
-
rapso schrieb:
;fricky schrieb:
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
doch, normalerweise ist das der fall. man muss sich schon muehe geben sowas simples kaputt zu implementieren.
Das bezweifel ich, sonst hätte RedHat wohl kaum ein Patent auf einen der Algorithmen angemeldet welche in der von mir zitierten Ringbuffer Datenstruktur zur Anwendung kommt.
-
Algorithmiker schrieb:
rapso schrieb:
;fricky schrieb:
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
doch, normalerweise ist das der fall. man muss sich schon muehe geben sowas simples kaputt zu implementieren.
Das bezweifel ich, sonst hätte RedHat wohl kaum ein Patent auf einen der Algorithmen angemeldet welche in der von mir zitierten Ringbuffer Datenstruktur zur Anwendung kommt.
P.S. Ich bezweifel das nicht nur deswegen, aber schaut euch einfach mal den von mir verlinkten Artikel an, dann wird die Problematik schon klar (der Artikel verweist übrigens auf ein Dokument des Autors, da findet ihr schöne Grafiken die die Problemsituationen illustrieren).
-
Algorithmiker schrieb:
rapso schrieb:
;fricky schrieb:
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
doch, normalerweise ist das der fall. man muss sich schon muehe geben sowas simples kaputt zu implementieren.
Das bezweifel ich, sonst hätte RedHat wohl kaum ein Patent auf einen der Algorithmen angemeldet welche in der von mir zitierten Ringbuffer Datenstruktur zur Anwendung kommt.
brauchst nicht zu bezweifeln, das ist schon seit jahrzehnten die realitaet.
RedHats patentierter ringbuffer ist fuer generische dinge, er ist abgesichert wenn mehrere feeder und consumer vorhanden sind. dabei musst du logischerweise synchronisieren.
das hat aber nichts mit diesem fall hier zu tun.
-
Algorithmiker schrieb:
Algorithmiker schrieb:
rapso schrieb:
;fricky schrieb:
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
doch, normalerweise ist das der fall. man muss sich schon muehe geben sowas simples kaputt zu implementieren.
Das bezweifel ich, sonst hätte RedHat wohl kaum ein Patent auf einen der Algorithmen angemeldet welche in der von mir zitierten Ringbuffer Datenstruktur zur Anwendung kommt.
P.S. Ich bezweifel das nicht nur deswegen, aber schaut euch einfach mal den von mir verlinkten Artikel an, dann wird die Problematik schon klar (der Artikel verweist übrigens auf ein Dokument des Autors, da findet ihr schöne Grafiken die die Problemsituationen illustrieren).
dein link? wo?
-
rapso schrieb:
hustbaer schrieb:
glaubt ihr dass der OP auch nur den funken einer chance hat, eure tollen lock-free ring-buffer hier zu verstehen, oder gar fehlerfrei zu implementieren?
ein ringbuffer der nur einen feeder und nur einen consumer hat ist in den allermeisten implementierungen lock-/waitfree. da muss man nichts an hyper funky dingen imlementieren.
ja wennst glaubst.
gibt ja auch keine CPUs die load-/store-reordering machen, oder wo man selbst für cache coherency sorgen muss. sowas wie memory-barriers ist eh überbewertet.mal davon abgesehen dass es IMO total plem ist mit lock-free algorithmen auf was draufzuhauen was IO-limitiert ist.
er sagte der IO thread ist sehr viel schneller.
sorry, mein fehler.
allerdings... wenn der IO thread schon schneller ist als der "verarbeitung-thread", dann hat es erst recht keinen sinn, irgendwelche schwer zu implementierenden optimierungen einzubauen, da man sie nicht spüren wird.
weiter hat lockfree und IO limitierung nichts miteinander zu tun.
ansichtssache. ich denke mir halt: wenn ich IO limitiert bin, dann werde ich mir keinen haxen aussreissen, um den CPU intensiven teil noch weiter zu beschleunigen.
eine stinknormale queue, sowas in der art wie C0de4Fun gepostet hat, ist hier sicher das beste.
ja, wenn man spatzen mit raketenwerfen ausschalten will.
nein. es ist das beste, wenn man mit wenig aufwand ein korrektes programm schreiben will. das nicht anfängt mist zu bauen, wenn es mal auf nem MIPS/PPC/... läuft. oder eben unnötig kompliziert ist.
-
rapso schrieb:
;fricky schrieb:
rapso schrieb:
das einfachste waere ein ringbuffer, das waere nicht nur lockfree, sondern auch waitfree.
aber nicht normalerweise, nur spezielle konstruktionen.
doch, normalerweise ist das der fall.
nee, weil die schreibfunktion mal kurz auf lesezeiger und die lesefunktion auf den schreibzeiger zugreifen muss.
rapso schrieb:
Jetzt ist der Thread 1 sehr viel schneller als der Thread 2.
in dem fall solltest du dir ueberlegen, ob du nicht lieber beide threads die dateien verarbeiten laesst, ansonsten ist das langsammer als es sein koennte.
oder nur einen thread nehmen, der suchen und verarbeiten nacheinander macht.
einen thread zu nutzen statt die arbeit auf zwei aufzuteilen soll welchen vorteil genau bringen?
[/quote]
z.b. hätte der OP dann diese frage garnicht stellen brauchen. möglicherweise bringt multithreading in seinem fall überhaupt nix, könnte sogar langsamer sein.
-
hustbaer schrieb:
rapso schrieb:
hustbaer schrieb:
glaubt ihr dass der OP auch nur den funken einer chance hat, eure tollen lock-free ring-buffer hier zu verstehen, oder gar fehlerfrei zu implementieren?
ein ringbuffer der nur einen feeder und nur einen consumer hat ist in den allermeisten implementierungen lock-/waitfree. da muss man nichts an hyper funky dingen imlementieren.
ja wennst glaubst.
gibt ja auch keine CPUs die load-/store-reordering machen, oder wo man selbst für cache coherency sorgen muss. sowas wie memory-barriers ist eh überbewertet.ja, das ist komplett irrelevant bei nem simplen ringbuffer. entweder es steht 0 drinnen, und dann kann der feeder was einfuegen, oder es steht ein ptr drinnen, dann kann der consumer 0 einfuegen. das ist dermassen primitiv. eine memory barrier brauchst du nur wenn du zwei writes hast die zueinander eine abhaengige reihenfolge haben, das gibt es hier nicht, weder im fall vom feeder, noch writer.
mal davon abgesehen dass es IMO total plem ist mit lock-free algorithmen auf was draufzuhauen was IO-limitiert ist.
er sagte der IO thread ist sehr viel schneller.
sorry, mein fehler.
allerdings... wenn der IO thread schon schneller ist als der "verarbeitung-thread", dann hat es erst recht keinen sinn, irgendwelche schwer zu implementierenden optimierungen einzubauen, da man sie nicht spüren wird.
deswegen schlug ich ja diese simple vor. etwas als zwischenbuffer damit beide asynchron laufen braucht man, denn es wuerde ja keinen sinn machen zwei threads zu haben wenn der eine darauf warten wuerde dem anderen einen wert zu uebergeben.
weiter hat lockfree und IO limitierung nichts miteinander zu tun.
ansichtssache. ich denke mir halt: wenn ich IO limitiert bin, dann werde ich mir keinen haxen aussreissen, um den CPU intensiven teil noch weiter zu beschleunigen.
das ist nicht wirklich IO relevant, denn wann auch immer das verhaeltniss von "arbeit" zu "sync" sich in richtung "arbeit" shiften, macht es weniger sinn den sync zu optimieren. da wuerde ich mir als auch keine arbeit machen.
jedoch, wenn man kommunizieren will, muss man sich schon gedanken machen wie es sicher ist.
von daher wuerde ich etwas waehlen was so trivial ist, dass man keine arbeit in sync investieren muss, weil es per definition sicher ist.
mein tipp mit ringbuffer war also nicht als optimierung gedacht fuer die laufzeit, sondern implementierungszeit.eine stinknormale queue, sowas in der art wie C0de4Fun gepostet hat, ist hier sicher das beste.
ja, wenn man spatzen mit raketenwerfen ausschalten will.
nein. es ist das beste, wenn man mit wenig aufwand ein korrektes programm schreiben will.
das ist deine meinung. ich hab meine 2cent dazu gegeben.
steht dem threadstarter frei selbst zu entscheiden was er machen moechte.