C++ TBB管道的输出不正确
我已经在文本文件中编写了一个具有不同值(100次)的C结构,如1.txt、2.txt。。。100.txtC++ 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将新结构写入光盘 基本上,它是结构的简单读写
我在Linux上使用Intel TBB。我创造了:
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;