5

時々実行され、時にはセグメンテーション違反が発生する並列プログラムがあります。実行可能ファイルは、3 つのスレッドで強制的に実行すると正常に実行されます (基本的には、単一のシリアル スレッドでも実行されます) が、他のスレッド値で強制的に実行すると、セグメンテーション エラーが発生します。シナリオは次のとおりです。

main.cメイン関数内から:

cilk_for ( line_count = 0; line_count != no_of_lines ; ++line_count )
{
     //some stuff here
     for ( j=line_count+1; j<no_of_lines; ++j )
     {
         //some stuff here
         final_result[line_count][j] = bf_dup_eleminate ( table_bloom[line_count], file_names[j], j );
         //some stuff here
     }
     //some stuff here
}

bf_dup_eleminatebloom-filter.cファイルからの関数:

int bf_dup_eleminate ( const bloom_filter *bf, const char *file_name, int j )
{
    int count=-1;
    FILE *fp = fopen (file_name, "rb" );
    if (fp)
    {
        count = bf_dup_eleminate_read ( bf, fp, j);
        fclose ( fp );
    }
    else
    {
        printf ( "Could not open file\n" );
    }
    return count;
}

bf_dup_eleminate_readbloom-filter.cファイルから:

int bf_dup_eleminate_read ( const bloom_filter *bf, FILE *fp, int j )
{
    //some stuff here
    printf ( "before while loop. j is %d ** workder id: **********%d***********\n", j, __cilkrts_get_worker_number());
    while (/*somecondition*/)
    {/*some stuff*/}
    //some stuff
}

このエラーはintel inspector次の場所から報告されました。

ID | Problem                         |  Sources       
P1 | Unhandled application exception | bloom-filter.c

コールスタックは次のとおりです。

exec!bf_dup_eleminate_read - bloom-filter.c:550
exec!bf_dup_eleminate - bloom-filter.c:653
exec!__cilk_for_001.10209 - main.c:341

同様gdbに、同じ場所でエラーを報告します。それは次のとおりです。

gdb次のエラーがあることがわかりました

0x0000000000406fc4 in bf_dup_eleminate_read (bf=<error reading variable: Cannot access memory at address 0x7ffff7edba58>, fp=<error reading variable: Cannot access memory at address 0x7ffff7edba50>, j=<error reading variable: Cannot access memory at address 0x7ffff7edba4c>) at bloom-filter.c:536

Line 536int bf_dup_eleminate_read ( const bloom_filter *bf, FILE *fp, int j )

追加の詳細:

今、私のブルームフィルターは次のように定義された構造です

struct bloom_filter
{
    int64_t m;      //size of bloom filter.
    int32_t k;      //number of hash functions.
    uint8_t *array;
    int64_t no_of_elements_added;
    int64_t expected_no_of_elements;
};

そのためのメモリは次のように割り当てられます。

    bloom_filter *bf = (bloom_filter *)malloc( sizeof(bloom_filter));
    if ( bf != NULL )
    {
        bf->m = filter_size*8;      /* Size of bloom filter */
        bf->k = num_hashes;
        bf->expected_no_of_elements = expected_no_of_elements;
        bf->no_of_elements_added = (int64_t)0;
        bf->array = (uint8_t *)malloc(filter_size);
        if ( bf->array == NULL )
        {
            free(bf);
            return NULL;
        }
    }  

のコピーは 1 つだけありbloom_filter、各スレッドは同じものにアクセスすることになっています (読み取りのみを変更していないため)。

過去4日間ここで立ち往生していて、抜け道が思いつかないので、誰か助けてください。最悪の部分は、3 つのスレッドで実行されていることです!!!

注: cilk_for は、cilk でスレッドを生成するための単なるキーワードです。

4

1 に答える 1

8

デバッガーが次のようなエラーを通知した場合:

0x0000000000406fc4 in bf_dup_eleminate_read (
    bf=<error reading variable: Cannot access memory at address 0x7ffff7edba58>,
    fp=<error reading variable: Cannot access memory at address 0x7ffff7edba50>,
    j=<error reading variable: Cannot access memory at address 0x7ffff7edba4c>
) at bloom-filter.c:536

536: int bf_dup_eleminate_read ( const bloom_filter *bf, FILE *fp, int j )

これは通常、関数エントリ コード (関数「プロローグ」と呼ばれる) がクラッシュしていることを示しています。つまり、スタックが破損し、CPU が 3 つのローカル変数のアドレスを計算してスタックにスペースを割り当てるときにクラッシュします。

私がチェックしたり、このエラーを修正しようとしたりすること (どれも動作することが保証されておらず、すでに試したことがあるかもしれません):

  1. プログラムの他の部分で宣言したローカル変数によって使用されるスペースをオーバーランしていないことを確認してください。

  2. ローカル変数として宣言され、プログラムの他の部分の関数から返されたポインターに書き込んでいないことを確認してください。

  3. 各スレッドには、宣言したすべてのローカル変数を処理するのに十分なスタック スペースがあることを確認してください。大きなスタックベースのバッファを宣言していますか? デフォルトのスレッドごとのスタック サイズは、コンパイラの設定 (この場合はcilkライブラリ) によって異なります。コンパイル時にスレッドごとのスタック サイズを増やしてみて、クラッシュが解消されるかどうかを確認してください。

運が良ければ、上記のいずれかで問題の原因を絞り込むことができるはずです。

于 2012-07-02T04:01:35.617 に答える