C++ TBB管道的输出不正确

C++ TBB管道的输出不正确,c++,multithreading,parallel-processing,tbb,C++,Multithreading,Parallel Processing,Tbb,我已经在文本文件中编写了一个具有不同值(100次)的C结构,如1.txt、2.txt。。。100.txt 我在Linux上使用Intel TBB。我创造了: 输入滤波器(顺序模式下的串行) TransformFIlter(串行顺序模式) 输出滤波器(串行顺序模式) InputFilter从文件中读取结构并将其传递给TransformFilter。 TrasnformFilter更新结构值并将其传递给OutputFilter。 OutputFilter将新结构写入光盘 基本上,它是结构的简单读写

我已经在文本文件中编写了一个具有不同值(100次)的C结构,如1.txt、2.txt。。。100.txt


我在Linux上使用Intel TBB。我创造了:

  • 输入滤波器(顺序模式下的串行)
  • TransformFIlter(串行顺序模式)
  • 输出滤波器(串行顺序模式)
  • InputFilter从文件中读取结构并将其传递给TransformFilter。 TrasnformFilter更新结构值并将其传递给OutputFilter。 OutputFilter将新结构写入光盘

    基本上,它是结构的简单读写应用程序。

    class InputFilter:公共tbb::filter{
    公众:
    输入滤波器(int);
    ~InputFilter();
    私人:
    int总流量;
    整数计数;
    结构视频处理对象输入对象;
    void*运算符()(void*);
    };
    InputFilter::InputFilter(intx)
    :过滤器(串行顺序){
    总流量=x;
    计数=1;
    }
    InputFilter::~InputFilter(){
    总流量=0;
    }
    void*InputFilter::operator()(void*){
    字符路径[50]={};
    sprintf(路径“input/%d.txt”,计数);
    printf(“路径:%s\n”,路径);
    文件*fp;
    fp=fopen(路径“r”);
    如果(fp==NULL | |计数>总|流){
    fclose(fp);
    printf(“\n*******找不到更多数据。正在终止******\n\n\n”);
    返回NULL;
    }
    fscanf(fp、%d、&input_obj.video_id);
    fscanf(fp、%s、&input\u obj.storage\u url);
    fscanf(fp、%s、&input\u obj.storage\u type);
    fscanf(fp、%d、&input\u obj.face\u detect);
    fscanf(fp、%d、&input_obj.face_recognized);
    fscanf(fp、%d、&input\u obj.scene\u识别);
    fscanf(fp、%d、&input\u obj.activity\u recognized);
    fscanf(fp、%d、&input\u obj.speech\u recognized);
    fclose(fp);
    计数++;
    返回和输入对象;
    }
    类TransformFilter:公共tbb::filter{
    公众:
    TransformFilter();
    ~TransformFilter();
    私人:
    结构视频处理对象输入变换;
    void*运算符()(void*);
    };
    TransformFilter::TransformFilter()
    :过滤器(串行顺序){
    }
    TransformFilter::~TransformFilter(){
    }
    void*TransformFilter::operator()(void*item){
    输入转换=*静态转换(项);
    输入_transform.video_id+=1000;
    strcat(输入转换存储url,“nabeel”);
    strcat(输入转换存储类型,“N”);
    输入_transform.face_detect+=1000;
    输入_transform.face_recognized+=1000;
    返回&输入_变换;
    }
    类OutputFilter:公共tbb::filter{
    公众:
    OutputFilter();
    ~OutputFilter();
    私人:
    结构视频处理对象输出对象;
    void*运算符()(void*);
    };
    OutputFilter::OutputFilter()
    :过滤器(串行顺序){
    int status=mkdir(“输出”,S|u IRWXU | S|u IRWXG | S|u IRWXO);
    如果(状态==-1)
    printf(“\n输出目录已存在\n\n”);
    }
    OutputFilter::~OutputFilter(){
    }
    void*OutputFilter::operator()(void*item){
    输出对象=*静态类型(项目);
    文件*fp;
    字符路径[50]={};
    sprintf(路径,“output//%d.txt”,output\u obj.video\u id-1000);
    printf(“输出路径:%s\t\t%d\n\n”,路径,输出对象视频\u id);
    if((fp=fopen(路径,“w”))==NULL){
    fprintf(stderr,“无法打开输出文件。\n”);
    返回NULL;
    }
    fprintf(fp,“%d\n”,输出对象视频标识);
    fprintf(fp,“%s\n”,输出对象存储地址);
    fprintf(fp,“%s\n”,输出对象存储类型);
    fprintf(fp,“%d\n”,输出对象面检测);
    fprintf(fp,“%d\n”,输出对象面);
    fprintf(fp,“%d\n”,输出对象场景);
    fprintf(fp,“%d\n”,输出对象活动);
    fprintf(fp,“%d\n”,输出对象语音识别);
    fclose(fp);
    返回NULL;
    }
    int main(){
    tbb::管道;
    输入滤波器输入滤波器(100);
    管道。添加_过滤器(输入_过滤器);
    变换滤波器变换滤波器;
    管道。添加_过滤器(转换_过滤器);
    输出滤波器输出滤波器;
    管道。添加_过滤器(输出_过滤器);
    tbb::tick_count t0=tbb::tick_count::now();
    tbb::task_scheduler_init init_parallel;
    管道运行(1);
    tbb::tick_count t1=tbb::tick_count::now();
    返回0;
    }
    
    使用少量文件(如5或10个)时,一切正常。当我读取大量文件(如50或100)时,问题就开始了。问题是:

    有时InputFilter读取10.txt文件并对其进行TransformFilter处理。但InputFilter立即读取11.txt。OutputFIlter跳过10.txt并处理11.txt


    如何确保不会发生这种情况?

    存在数据竞争,因为视频处理对象被放置在过滤器结构中,并在过滤器之间通过引用传递(当然是并行运行的)。因此,当
    InputFilter
    开始处理将新数据读取到其video\u process\u对象中的下一个令牌,而第一个令牌刚刚开始按
    TransformFilter
    中的相同地址读取数据时,就会出现这种情况:

         Token 1                ||         Token 2
    input_filter.operator()     ||
    transform_filter.operator() ||  input_filter.operator()
    ...
    
    要解决此问题,请动态分配数据,例如:

    struct video_process_object *input_obj_ptr = new video_process_object;
    fscanf( fp, "%d", &input_obj_ptr->video_id );
    ...
    return input_obj_ptr;
    

    并在最后一个筛选器中取消分配它,因为它的返回值无论如何都会被忽略。 幻灯片中的49-50绘制了类似的代码

    最后,让我来挑战您对tbb::pipelene和串行顺序过滤器类型的选择。报告说:

    在实际应用中,最好使用并行滤波器,因为它们允许并行加速。如果一个过滤器必须是串行的,那么在实际应用中最好使用无序变量,因为它对处理顺序的限制较少

    由于处理和文件是独立的,因此我认为没有理由将此附加的“有序”限制放在一起。为了更好的结构化代码考虑另一个引用:

    Function parallel_pipeline提供了一种强类型lambda友好的方法来构建和运行管道

    问题(如果有)在过滤器定义中。请将它们添加到代码中。阿尔索
    struct video_process_object *input_obj_ptr = new video_process_object;
    fscanf( fp, "%d", &input_obj_ptr->video_id );
    ...
    return input_obj_ptr;