簡體   English   中英

TBB管道輸出不正確

[英]incorrect output with TBB pipeline

我在文本文件(例如1.txt,2.txt ... 100.txt )中編寫了具有不同值(100倍)的C結構


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

  1. InputFilter(serial_in_order模式)
  2. TransformFIlter(串行順序模式)
  3. OutputFilter(Serial_in_order模式)

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)時,問題就開始了。問題是:

有時InputFilter讀取10.txt文件,然后TransformFilter對其進行處理。 但是,InputFilter立即讀取11.txt。 OutputFIlter跳過10.txt並處理11.txt。

我如何確保不會發生這種情況?

有一個數據爭用,因為video_process_objects放置在過濾器結構內,並通過過濾器之間的引用(當然是並行運行)傳遞的。 因此,您會遇到以下情況: InputFilter開始處理下一個令牌,將新數據讀取到其video_process_object中,而第一個令牌剛剛開始通過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和serial_in_order過濾器類型的選擇。 TBB參考資料》說:

實際應用中最好使用並行濾波器,因為它們可以並行加速。 如果過濾器必須是串行的,則在實際可行時最好使用亂序變量,因為它對處理順序的約束更少。

由於處理和文件是獨立的,我認為沒有理由將這個附加的“按順序”限制。 為了結構更好的代碼,還要考慮另一個引號:

函數parallel_pipeline提供了一種強類型的lambda友好方式來構建和運行管道。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM