gpt4 book ai didi

c++ - TBB 管道输出不正确

转载 作者:太空宇宙 更新时间:2023-11-04 11:34:29 25 4
gpt4 key购买 nike

我在1.txt, 2.txt ... 100.txt

等文本文件中写了一个具有不同值(100次)的C结构

我在 Linux 上使用英特尔 TBB。我创建了:

  1. 输入过滤器(serial_in_order 模式)
  2. TransformFIlter(serial_in_order 模式)
  3. OutputFilter (Serial_in_order MODE)

InputFilter 从文件中读取结构并将其传递给 TransformFilter。TrasnformFilter 更新结构值并将其传递给 OutputFilter。OutputFilter 将新结构写入磁盘。

基本上,它是一个结构体的简单读写应用。

class InputFilter: public tbb::filter {
public:
InputFilter( int );
~InputFilter();
private:
int total_streams;
int count;
struct video_process_object input_obj;
void* operator()( void* );
};

InputFilter::InputFilter( int x )
: filter( serial_in_order ) {
total_streams = x;
count = 1;
}

InputFilter::~InputFilter() {
total_streams = 0;
}

void* InputFilter::operator()( void* ) {
char path[50] = { };
sprintf( path, "input//%d.txt", count );
printf( "Path : %s\n", path );
FILE *fp;
fp = fopen( path, "r" );

if( fp == NULL || count > total_streams ) {
fclose( fp );
printf( "\n*******Cannot find more data.Terminating********\n\n\n" );
return NULL;
}

fscanf( fp, "%d", &input_obj.video_id );
fscanf( fp, "%s", &input_obj.storage_url );
fscanf( fp, "%s", &input_obj.storage_type );
fscanf( fp, "%d", &input_obj.face_detect );
fscanf( fp, "%d", &input_obj.face_recognise );
fscanf( fp, "%d", &input_obj.scene_recognise );
fscanf( fp, "%d", &input_obj.activity_recognise );
fscanf( fp, "%d", &input_obj.speech_recognise );
fclose( fp );

count++;
return &input_obj;
}

class TransformFilter: public tbb::filter {
public:
TransformFilter();
~TransformFilter();
private:
struct video_process_object input_transform;
void* operator()( void* );
};

TransformFilter::TransformFilter()
: filter( serial_in_order ) {
}

TransformFilter::~TransformFilter() {
}

void* TransformFilter::operator()( void *item ) {

input_transform = *static_cast<struct video_process_object*>( item );

input_transform.video_id += 1000;
strcat( input_transform.storage_url, " nabeel" );
strcat( input_transform.storage_type, " N" );
input_transform.face_detect += 1000;
input_transform.face_recognise += 1000;

return &input_transform;
}

class OutputFilter: public tbb::filter {
public:
OutputFilter();
~OutputFilter();
private:
struct video_process_object output_obj;
void* operator()( void* );
};

OutputFilter::OutputFilter()
: filter( serial_in_order ) {
int status = mkdir( "output", S_IRWXU | S_IRWXG | S_IRWXO );
if( status == -1 )
printf( "\nOutput directory already exists\n\n" );
}

OutputFilter::~OutputFilter() {
}

void* OutputFilter::operator()( void *item ) {

output_obj = *static_cast<struct video_process_object*>( item );

FILE *fp;

char path[50] = { };
sprintf( path, "output//%d.txt", output_obj.video_id - 1000 );
printf( "Output Path : %s\t\t %d\n\n", path, output_obj.video_id );

if( (fp = fopen( path, "w" )) == NULL ) {
fprintf( stderr, "Cannot open output file.\n" );
return NULL;
}

fprintf( fp, "%d\n", output_obj.video_id );
fprintf( fp, "%s\n", output_obj.storage_url );
fprintf( fp, "%s\n", output_obj.storage_type );
fprintf( fp, "%d\n", output_obj.face_detect );
fprintf( fp, "%d\n", output_obj.face_recognise );
fprintf( fp, "%d\n", output_obj.scene_recognise );
fprintf( fp, "%d\n", output_obj.activity_recognise );
fprintf( fp, "%d\n", output_obj.speech_recognise );

fclose( fp );
return NULL;
}

int main() {
tbb::pipeline pipeline;

InputFilter input_filter( 100 );
pipeline.add_filter( input_filter );

TransformFilter transform_filter;
pipeline.add_filter( transform_filter );

OutputFilter output_filter;
pipeline.add_filter( output_filter );

tbb::tick_count t0 = tbb::tick_count::now();

tbb::task_scheduler_init init_parallel;
pipeline.run( 1 );
tbb::tick_count t1 = tbb::tick_count::now();

return 0;
}

对于少量文件(如 5 或 10),一切正常。当我读取大量文件(如 50 或 100)时,问题就开始了。问题是:

Sometimes InputFilter reads 10.txt file and TransformFilter processes it. But immediately InputFilter reads 11.txt. OutputFIlter skips 10.txt and processes 11.txt.

我怎样才能确保这不会发生?

最佳答案

存在数据竞争,因为 video_process_objects 被放置在过滤器结构中并在过滤器之间通过引用传递(当然并行运行)。因此,当 InputFilter 开始处理下一个将新数据读入其 video_process_object 的 token 时,您会遇到这样的情况,而第一个 token 刚刚开始通过 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;

并在最后一个过滤器中释放它,因为它的返回值无论如何都会被忽略。this old presentation 中的幻灯片 49-50勾勒出类似的代码。

最后,让我挑战一下您对 tbb::pipelene 和 serial_in_order 过滤器类型的选择。 TBB Reference说:

Parallel filters are preferred when practical because they permit parallel speedup. If a filter must be serial, the out of order variant is preferred when practical because it puts less contraints on processing order.

由于处理和文件是独立的,因此我看不出有什么理由要加上这个额外的“有序”限制。为了结构更好的代码而考虑的另一句话:

Function parallel_pipeline provides a strongly typed lambda-friendly way to build and run pipelines.

关于c++ - TBB 管道输出不正确,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23356308/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com