2016-11-24 1 views
1

Das ist, was ich versuche zu erreichen:Timeout ein TBB-Pipeline Filter

Ich TBB's Pipeline zur Verarbeitung verwendet wird. Ich habe mehrere Filter in der Pipeline und ich brauche die Filter so schnell wie möglich, da dies eine Echtzeitanwendung ist. Einer der Filter kann manchmal länger dauern, als ich es mir leisten kann, also möchte ich irgendwie einen Timeout für diesen bestimmten Filter setzen.

Nachdem er eine Weile suchen fand ich die folgende Lösung, die in der Regel funktioniert, aber hat seine Probleme:

Wenn die Filter erstellt wird, erstelle ich ein Ereignis HANDLE

m_Event = CreateEvent(NULL, FALSE, FALSE, NULL); 

die Filter dann, async und wartet auf das Ereignis ruft eine Funktion

... 
auto funcBind = std::bind(&MyFunc, ...) 
auto function = std::async(std::launch::async, funcBind, m_Event ...); 
long res = WaitForSingleObject(m_Event, delayMS); 
auto myFuncRes = function.get() 
if (res == WAIT_OBJECT_0 && (bool)myFuncRes) 
{ 
    // MyFunc Finished successfuly 
} 
else if (res == WAIT_TIMEOUT) 
{ 
    // Timeout expired 
} 
else 
{ 
    // MyFunc failed 
} 
... 
return; 

Kurz bevor die Funktion MyFunc kehrt es unter Verwendung der Signale Ereignis

SetEvent(event); 

So, jetzt, wenn das delayMS Timeout abläuft, werden die TBB-Filter die gesamte Pipeline nicht verzögern. Das Problem ist, dass MyFunc immer noch im Hintergrund läuft, es hört nicht auf.

Meine Frage ist, gibt es eine bessere Möglichkeit, ein Timeout für einen TBB-Filter zu setzen, und gibt es eine Lösung zum Beenden MyFunc Ausführung, sobald ein Timeout erreicht wurde (Ich würde lieber keine Timer oder Timing-Prüfungen verwenden innerhalb es, vielleicht irgendwie, um das Ereignis zu verwenden und zu überprüfen, ob es durch den Filter oder etwas genommen wurde)

Antwort

3

Ist es möglich, Prüfpunkte zu Ihrer langwierigen Aufgabe hinzuzufügen? Wenn dies möglich ist, können Sie task_group oder task_group_context verwenden, um die Ausführung einer Aufgabe oder mehrerer Aufgaben abzubrechen. Damit dies jedoch bei einer lang andauernden Task ordnungsgemäß funktioniert, müssen Sie sie manuell unterbrechen, indem Sie unter tbb::task::self().is_cancelled() auf die Abbruchanforderung prüfen und die Ausführung der Task beenden.

Anschließend können Sie zusätzliche Threads zum Überwachen der Zeit und zum Senden von Stornierungsanforderungen an die Aufgabengruppen verwenden, die länger als zulässig dauern. Auf diese Weise kann Ihre Berechnung im selben Thread bleiben wie die Pipeline, wodurch der Aufwand beim Wechseln und Synchronisieren zwischen Threads reduziert wird.

Wenn Ihr lang laufender Thread I/O-gebunden ist, haben Sie eine weitere Option, indem Sie Async-I/O einführen, das viel besser mit TBB interagiert und Ihnen die gesamte Kontrolle über die Zeit gibt.

+0

Danke. Wird durch das Abbrechen der task_group die Pipeline gestoppt? Weil ich nur den langen Filter des spezifischen Schrittes stoppen möchte. Ich möchte, dass die Pipeline wie gewohnt weitergeht –

+0

Nein, wenn Sie nur Filter im Kontext von task_group oder anderen 'task_group_context :: isolated' Bereich ausführen und abbrechen und nicht den Kontext der gesamten Pipeline. Es bedeutet, dass Sie innerhalb des Filter-Funktors einen anderen verschachtelten Algorithmus wie 'task_group :: run_and_wait()' ausführen wollen, so dass er in einem anderen Kontext ausgeführt wird – Anton