caffe网络在多线程中没法使用GPU的解决方案 | cpp caffe net run in multiple threads

本文首发于我的博客kezunlin.me/post/8d877e…,欢迎阅读!ios

cpp caffe net run in multiple threadsgit

Guide

set_mode

Caffe fails to use GPU in a new thread ???see heregithub

the `Caffe::mode_` variable that controls this is thread-local,
    so ensure you’re calling `caffe.set_mode_gpu()` in each thread
    before running any Caffe functions. That should solve your issue.复制代码
Caffe set_mode GPU 在多线程下失效
    在main thread中设置GPU模式,在worker thread中调用网络进行检测,
    GPU模式不起效,默认仍然使用CPU模式,因此速度很慢,和GPU相比慢了
    10倍左右。复制代码
解决方案:在子线程中set_mode,而后调用网络进行检测。
    (1)建立网络在main thread。static 网络存储在全局静态数据区。
    worker thread能够直接使用。
    (2) 在worker thread中检测,须要在子线程中set_mode,而后调用网络进行检测。复制代码
结论:
    (1)caffe的set_mode所在的线程必须和使用nets进行forward的线程相同。不然默认使用CPU模式,速度会很慢。
    (2)caffe的nets初始化能够在main thread也能够在worker thread。复制代码

code example

#include <iostream>
#include <string>
#include <thread>

#include <gtest/gtest.h>
#include <glog/logging.h>

#include <boost/date_time/posix_time/posix_time.hpp>  

// opencv
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;

#include "algorithm/algorithm.h"
using namespace kezunlin::algorithm;

#pragma region net-demo

void topwire_demo(bool run_in_worker_thread)
{
    if (run_in_worker_thread) {
        CaffeApi::set_mode(true, 0, 1234);// set in worker thread-1, use GPU-0
    }
    
    // do net detect 
    // ...
}

void railway_demo(bool run_in_worker_thread)
{
    if (run_in_worker_thread) {
        CaffeApi::set_mode(true, 0, 1234);// set in worker thread-1, use GPU-0
    }
    
    // do net detect 
    // ...
}

void sidewall_demo(bool run_in_worker_thread)
{
    if (run_in_worker_thread) {
        CaffeApi::set_mode(true, 0, 1234);// set in worker thread-1, use GPU-0
    }

    // do net detect 
    // ...
}

void lockcatch_demo(bool run_in_worker_thread)
{
    if (run_in_worker_thread) {
        CaffeApi::set_mode(true, 0, 1234);// set in worker thread-1, use GPU-0
    }

    // do net detect 
    // ...
}

#pragma endregion


#pragma region worker-thread-demo

void worker_thread_topwire_demo(bool run_in_worker_thread)
{
    std::thread thr(topwire_demo, run_in_worker_thread);
    thr.join();
}

void worker_thread_railway_demo(bool run_in_worker_thread)
{
    std::thread thr(railway_demo, run_in_worker_thread);
    thr.join();
}

void worker_thread_sidewall_demo(bool run_in_worker_thread)
{
    std::thread thr(sidewall_demo, run_in_worker_thread);
    thr.join();
}

void worker_thread_lockcatch_demo(bool run_in_worker_thread)
{
    std::thread thr(lockcatch_demo, run_in_worker_thread);
    thr.join();
}

#pragma endregion

enum DETECT_TYPE {
    SET_IN_MAIN_DETECT_IN_MAIN, // 主线程set_mode,主线程检测,40ms左右,使用GPU
    SET_IN_WORKER_DETECT_IN_WORKER, // 子线程set_mode,子线程检测,40ms左右,使用GPU
    SET_IN_MAIN_DETECT_IN_WORKER // 主线程set_mode,子线程检测,400ms左右,慢了10倍左右,没有使用GPU
};

void thread_demo()
{
    DETECT_TYPE detect_type = SET_IN_MAIN_DETECT_IN_MAIN;
    detect_type = SET_IN_WORKER_DETECT_IN_WORKER;
    detect_type = SET_IN_MAIN_DETECT_IN_WORKER;

    init_algorithm_api();

    switch (detect_type)
    {
    case SET_IN_MAIN_DETECT_IN_MAIN:
        topwire_demo(false);
        railway_demo(false);
        sidewall_demo(false);
        lockcatch_demo(false);
        break;
    case SET_IN_WORKER_DETECT_IN_WORKER:
        worker_thread_topwire_demo(true);
        worker_thread_railway_demo(true);
        worker_thread_sidewall_demo(true);
        worker_thread_lockcatch_demo(true);
        break;
    case SET_IN_MAIN_DETECT_IN_WORKER:
        worker_thread_topwire_demo(false);
        worker_thread_railway_demo(false);
        worker_thread_sidewall_demo(false);
        worker_thread_lockcatch_demo(false);
        break;
    default:
        break;
    }

    free_algorithm_api();
}

void test_algorithm_api()
{
    thread_demo();
}

TEST(algorithn_test, test_algorithm_api) {
    test_algorithm_api();
}复制代码

  • SETINMAINDETECTIN_MAIN, // 主线程set_mode,主线程检测,40ms左右,使用GPU
  • SETINWORKERDETECTIN_WORKER, // 子线程set_mode,子线程检测,40ms左右,使用GPU
  • SETINMAINDETECTIN_WORKER // 主线程set_mode,子线程检测,400ms左右,慢了10倍左右,没有使用GPU

Reference

History

  • 20180712: created.

Copyright

相关文章
相关标签/搜索