Caffe特征提取阻止其他执行线程(Qt / C ++)

时间:2016-01-09 04:27:45

标签: c++ multithreading qt blocking caffe

背景

我正在开发一个包含三个线程的Qt应用程序:mainthread1thread2

  • main创建,启动并显示thread1thread2的结果 thread1,同时也反复向他们提供输入。

  • thread2 n 执行一次密集计算(~1s) 输入,忽略所有其他输入。大部分时间都用于特征提取 使用Caffe framework

  • thread1对每个输入执行快速计算(~20ms)。但 每个 n + 1 输入取决于输入 n thread1的输出。

在线程执行期间,thread2在使用Caffe网络提取功能时似乎阻止了thread1。但是,thread2在其他处理步骤(例如网络输入预处理)中执行阻止thread1

起初,我认为这是由未满足的依赖引起的:即thread2“阻止”thread2,因为输入(例如) 2n + 1 已准备就绪由thread1处理,但输入 2n 尚未由thread2完全处理。

然而,通过分析执行流程,我注意到在满足依赖性时发生了这种“阻塞”行为:即让 n = 10,thread1将在输入15处暂停执行thread2正在从输入20中提取Caffe功能。

问题

如何在Caffe功能提取过程中阻止thread1阻止// !!! PROBLEM: ...

代码

下面是我的代码的精简版本,它显示了我的程序的关键组件和逻辑。

我在评论thread1worker.cpp中突出显示了问题,可以在featureengine.cppint main(int argc, char* argv[]) { QApplication app(argc, argv); qRegisterMetaType<Mat>("Mat"); Camera camera; // grabs camera frame every 30ms, emitting newFrame(frame) /* thread1 */ QThread* thread1 = new QThread(); Thread1Worker* thread1_worker = new Thread1Worker(); thread1_worker->moveToThread(thread1); QThread::connect(&camera, SIGNAL(newFrame(Mat)), thread1_worker, SLOT(doWork(Mat))); QThread::connect(thread1, SIGNAL(finished()), thread1_worker, SLOT(deleteLater())); QThread::connect(thread1, SIGNAL(finished()), thread1, SLOT(deleteLater())); /* thread2 */ ImageQueue* thread2_images = new ImageQueue(); QThread::connect(camera, SIGNAL(newFrame(Mat)), thread2_images, SLOT(add(Mat))); QThread* thread2 = new QThread(); Thread2Worker* thread2_worker = new Thread2Worker(thread2_images); thread2_worker->moveToThread(thread2); QThread::connect(thread2_worker, SIGNAL(workFinished(OutputType)), thread2_worker, SLOT(addThread1Result(OutputType))); QThread::connect(thread2, SIGNAL(finished()), thread2_worker, SLOT(deleteLater())); QThread::connect(thread2, SIGNAL(finished()), thread2, SLOT(deleteLater())); /* start threads */ thread1->start(); thread2->start(); camera->start(); return app.exec(); } 中找到。

main.cpp中:

Thread1Worker::Thread1Worker()
{
    thread1_interval = 10; // this is "n"
    is_initialized = false;
}

void Thread1Worker::doWork(Mat frame)
{
    if (!is_initialized)
        initialize();

    // process only every nth frame
    if (!isThread1Frame())
        return;

    // ... break frame up into multiple image patches

    // !!! PROBLEM: this call blocks thread2
    vector<vector<float> > features = feature_engine->extractFeatures(patches);

    // ... use features to compute output

    frame_count++;

    emit workFinished(output);
}

void Thread1Worker::initialize()
{
    InitGoogleLogging("caffe-demo");
    feature_engine = new FeatureEngine();
    is_initialized = true;
}

bool Thread1Worker::isThread1Frame()
{
    return frame_count % thread1_interval == 0;
}

thread1worker.cpp:

void Thread2Worker::addThread1Result(OutputType output)
{
    if (!is_initialized)
        initialize();

    thread1_output_queue.push(output);
    thread1_count++;

    processFrames();
}

void Thread2Worker::processFrames()
{
    size_t num_process = (thread1_count * thread1_interval) - process_count;
    size_t num_queue = thread2_images->size();
    for (size_t i = 0; i < num_process && i < num_queue; i++)
    {
        Mat frame = thread2_images->get();

        if (isThread1Frame()
        {
            curr_result = thread1_output_queue.front();
            thread1_output_queue.pop();
        }
        else
        {
            curr_result = propagator->propagate(prev_result);
        }

        // update
        prev_result = curr_result;

        emit resultReady(curr_result);
    }
}

void Thread2Worker::initialize()
{
    propagator = new Propagator();
    is_initialized = true;
}

bool Thread2Worker::isThread1Frame()
{
    return process_count % thread1_interval == 0;
}

thread2worker.cpp:

vector<vector<float> > FeatureEngine::extractFeatures(const vector<Mat>& images)
{
    // setup Caffe network for feature extraction:

    Blob<float>* input_layer = net->input_blobs()[0];

    int num_images = images.size();
    int height = input_geometry.height;
    int width = input_geometry.width;
    input_layer->Reshape(num_images, num_channels, height, width);
    net->Reshape();

    vector<Mat> input_channels;
    wrapInputLayer(input_channels);
    preprocess(images, &input_channels);


    // !!! PROBLEM: this ~1s computation blocks thread2
    // details: https://github.com/BVLC/caffe/blob/master/src/caffe/net.cpp#L594
    net->ForwardPrefilled();

    // copy Caffe network output to features vector
    vector<vector<float> > features;
    // ...

    return features;
}

featureengine.cpp:

{{1}}

0 个答案:

没有答案