Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Caffe特征提取阻止其他执行线程(Qt/C+;+;)_C++_Multithreading_Qt_Blocking_Caffe - Fatal编程技术网

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

C++ Caffe特征提取阻止其他执行线程(Qt/C+;+;),c++,multithreading,qt,blocking,caffe,C++,Multithreading,Qt,Blocking,Caffe,背景 我正在开发一个具有三个线程的Qt应用程序:main、thread1和thread2 main创建、启动并显示thread1的结果,以及 thread2,同时迭代地向它们输入 thread1每n次执行一次密集计算(~1s) 输入,忽略所有其他输入。大部分时间用于特征提取 使用 thread2对每个输入执行快速计算(~20ms)。但是 每n+1个输入取决于将输入n馈送至thread1的输出 在线程执行期间,当使用Caffe网络提取特征时,thread1似乎会阻止thread2。但是,thr

背景

我正在开发一个具有三个线程的Qt应用程序:
main
thread1
thread2

  • main
    创建、启动并显示
    thread1
    的结果,以及
    thread2
    ,同时迭代地向它们输入

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

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

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

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

然而,通过分析执行流,我注意到在满足依赖关系时出现了这种“阻塞”行为:即,如果n=10,
thread2
将在输入15处暂停执行,而
thread1
从输入20中提取Caffe特征

问题

在Caffe特征提取期间,如何防止
thread2
阻塞
thread1

代码

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

我已经在评论中强调了这个问题!!!问题:…,可在
thread1worker.cpp
featureengine.cpp
中找到

main.cpp:

int 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();
}
intmain(intargc,char*argv[])
{
QApplication应用程序(argc、argv);
qRegisterMetaType(“Mat”);
Camera Camera;//每30毫秒抓取一帧,发出新帧(帧)
/*螺纹1*/
QThread*thread1=新的QThread();
Thread1Worker*thread1_worker=新的Thread1Worker();
thread1\u worker->moveToThread(thread1);
QThread::连接(&摄像头,信号(新帧(Mat)),
螺纹1_工,槽(销钉(垫));
QThread::connect(线程1,信号(finished()),
线程1_worker,插槽(deleteLater());
QThread::connect(线程1,信号(finished()),
线程1,插槽(deleteLater());
/*螺纹2*/
ImageQueue*thread2_images=新建ImageQueue();
QThread::connect(摄像头、信号(新帧(Mat)),
螺纹2_图像,插槽(添加(垫));
QThread*thread2=新的QThread();
Thread2Worker*thread2\u worker=新的Thread2Worker(thread2\u图像);
thread2\u worker->moveToThread(thread2);
QThread::connect(thread2_worker,信号(workFinished(OutputType)),
线程2_工作线程,插槽(addThread1Result(OutputType));
QThread::connect(线程2,信号(finished()),
线程2_工作线程,插槽(deleteLater());
QThread::connect(线程2,信号(finished()),
线程2,插槽(deleteLater());
/*开始线程*/
thread1->start();
thread2->start();
摄像头->开始();
返回app.exec();
}
thread1worker.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;
}
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;
}
Thread1Worker::Thread1Worker()
{
thread1\u interval=10;//这是“n”
is_initialized=false;
}
空螺纹1工装::销钉(垫架)
{
如果(!已初始化)
初始化();
//仅每N帧处理一次
如果(!isThread1Frame())
返回;
//…将帧分解为多个图像块
//!!!问题:此调用阻止thread2
矢量特征=特征\引擎->提取特征(面片);
//…使用功能计算输出
帧计数++;
发出已完成的工作(输出);
}
void Thread1Worker::initialize()
{
InitGoogleLogging(“caffe演示”);
特征引擎=新特征引擎();
is_initialized=true;
}
bool Thread1Worker::isThread1Frame()
{
返回帧计数%thread1\u间隔==0;
}
thread2worker.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;
}
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;
}
void Thread2Worker::addThread1Result(OutputType输出)
{
如果(!已初始化)
初始化();
线程1_输出_队列。推送(输出);
线程1_计数++;
processFrames();
}
void Thread2Worker::processFrames()
{
大小\u t num\u进程=(线程1\u计数*线程1\u间隔)-进程数;
size_t num_queue=thread2_images->size();
对于(大小i=0;iget();
if(isThread1Frame()
{
curr_result=thread1_output_queue.front();
thread1_output_queue.pop();
}
其他的
{
当前结果=传播者->传播(上一个结果);
}
//更新
上一次结果=当前结果;
发出结果(当前结果);
}
}
void Thread2Worker::initialize()
{
传播者=新的传播者();
is_initialized=true;
}
bool Thread2Worker::isThread1Frame()
{
返回进程计数%thread1\u间隔==0;
}
featureengine.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;
}
vector FeatureEngine::extractFeatures(常量向量和图像)
{
//为特征提取设置Caffe网络:
Blob*input_layer=net->input_blobs()[0];
int num_images=images.size();
int height=输入_几何体高度;
int width=输入_geometry.width;
输入\u层->重塑(num\u图像、num\u通道、高度、宽度);
net->重塑();
矢量输入信道;
wrapInputLayer(输入信道);
预处理(图像和输入通道);
//!!!问题:此~1s计算阻塞线程2
//详情:https://github.com/BVLC/caffe/blob/m