2017-03-29 3 views
1

Ich habe eine Multithreading-Anwendung, die die GPU verwendet, die von Natur aus single-threaded ist, und die tatsächlichen APIs, die ich verwende, cv::gpu::FAST_GPU stürzt ab, wenn ich versuche, sie multi-threaded zu verwenden. so dass im Grunde habe ich:Bedingte Übernahme eines std :: mutex

static std::mutex s_FAST_GPU_mutex; 

{ 
    std::lock_guard<std::mutex> guard(s_FAST_GPU_mutex); 
    cv::gpu::FAST_GPU(/*params*/)(/*parameters*/); 
} 

nun den Code Benchmarking zeigt mir FAST_GPU() in Isolation ist schneller als die CPU FAST(), aber in der tatsächlichen Anwendung meine anderen Threads viel Zeit für die Sperre warten verbringen, so dass die Gesamt der Durchsatz ist schlechter.

Blick durch die Dokumentation und at this answer es scheint, dass dies möglich sein könnte:

static std::mutex s_FAST_GPU_mutex; 
static std::unique_lock<std::mutex> s_FAST_GPU_lock(s_FAST_GPU_mutex, std::defer_lock); 

{ 
    // Create an unlocked guard 
    std::lock_guard<decltype(s_FAST_GPU_lock)> guard(s_FAST_GPU_lock, std::defer_lock); 
    if (s_FAST_GPU_lock.try_lock()) 
    { 
     cv::gpu::FAST_GPU(/*params*/)(/*parameters*/); 
    } 
    else 
    { 
     cv::FAST(/*parameters*/); 
    } 
} 

Dies wird jedoch nicht kompiliert als std::lock_guard nur eine std::adopt_lock akzeptiert. Wie kann ich das richtig umsetzen?

+1

Ich bin nicht Sicher, warum du einen statischen 'unique_lock' verwendest, da normalerweise nicht 2 Threads Zugriff auf denselben' unique_lock' haben sollen. Das heißt, ich würde die s_FAST_GPU_LOCK entfernen und dann 'std :: try_to_lock' verwenden und testen, ob es mit' ownes_lock' erfolgreich war. –

+0

@DaveS Ahh, ich sehe - 'mutex.try_lock()' dann 'lock_guard <> (std :: adople_lock)'? Bitte mach das zu einer Antwort. –

Antwort

9

Es ist eigentlich unsicher, eine unique_lock von mehreren Threads gleichzeitig zugänglich zu haben. Ich kenne den opencv-Teil Ihrer Frage nicht, daher konzentriert sich diese Antwort auf die Verwendung von Mutex/Sperren.

static std::mutex s_FAST_GPU_mutex; 
{ 
    // Create a unique lock, attempting to acquire 
    std::unique_lock<std::mutex> guard(s_FAST_GPU_mutex, std::try_to_lock); 
    if (guard.owns_lock()) 
    { 
     cv::gpu::FAST_GPU(/*params*/)(/*parameters*/); 
     guard.unlock(); // Or just let it go out of scope later 
    } 
    else 
    { 
     cv::FAST(/*parameters*/); 
    } 
} 

Diese versucht, die Sperre zu erwerben, wenn es gelingt, verwendet FAST_GPU, und gibt dann die Sperre. Wenn die Sperre wurde bereits erworben, geht dann nach unten den zweiten Zweig unter Berufung auf FAST

+0

Das sieht gut aus und folgt genauer dem Muster des einfachen Falls, also sollte es einfacher zu verstehen sein als meine Vorschläge. –

+0

Naja, es stellt sich heraus, dass die reine CPU-Version schneller ist als das obige, um die Arbeit zu teilen. Es funktioniert wie du es beschreibst, also ist es an der Zeit, den GPU-Profiler zu durchbrechen, um zu sehen, ob etwas anderes die GPU in den Wahnsinn treibt. –

+2

Ich kann nicht sicher sagen, aber das Aufteilen der Arbeit wird mit ziemlicher Sicherheit einen Befehlspuffer auf der GPU erzwingen, wann immer die CPU die Daten berührt, da sie diese Daten neu laden muss, könnte dieser Befehlspuffer die GPU verursachen Operation zum Sperren innerhalb des Schlosses, abhängig von der Implementierung. –

5

Sie std::lock_guard verwenden können, wenn Sie den Mutex im verriegelten Zustand annehmen , wie folgt aus:

{ 
    if (s_FAST_GPU_mutex.try_lock()) 
    { 
     std::lock_guard<decltype(s_FAST_GPU_lock)> guard(s_FAST_GPU_mutex, std::adopt_lock); 
     cv::gpu::FAST_GPU(/*params*/)(/*parameters*/); 
    } 
    else 
    { 
     cv::FAST(/*parameters*/); 
    } 
} 
Verwandte Themen