2017-06-17 12 views
2

私はデータをchar配列に格納しています。そこからfloatとint変数を読み取る必要があります。 このコードはCPU上で正常に動作します:OpenCL:GPUでの型キャスト

global float *p; 
p = (global float*)get_pointer_to_the_field(char_array, index); 
*p += 10; 

しかし、GPU上で、私はエラーを取得-5:CL_OUT_OF_RESOURCESを。読み込み自体は機能しますが、値を使って何かを行うと(この場合は10を追加すると)エラーが発生します。どうすれば修正できますか?

更新:

これは、GPU上で動作します。

float f = *p; 
f += 10; 

しかし、私はまだ戻って配列にこの値を書き込むことはできません。

global void write_value(global char *data, int tuple_pos, global char *field_value, 
        int which_field, global int offsets[], global int *num_of_attributes) { 

    int tuple_size = offsets[*num_of_attributes]; 
    global char *offset = data + tuple_pos * tuple_size; 
    offset += offsets[which_field]; 

    memcpy(offset, field_value, (offsets[which_field+1] - offsets[which_field])); 
} 

global char *read_value(global char *data, int tuple_pos, 
        int which_field, global int offsets[], global int *num_of_attributes) { 
    int tuple_size = offsets[*num_of_attributes]; 
    global char *offset = data + tuple_pos * tuple_size; 
    offset += offsets[which_field]; 
    return offset; 
} 

kernel void update_single_value(global char* input_data, global int* pos, global int offsets[], 
          global int *num_of_attributes, global char* types) { 
    int g_id = get_global_id(1); 
    int attr_id = get_global_id(0); 
    int index = pos[g_id]; 

    if (types[attr_id] == 'f') { // if float 

     global float *p; 
     p = (global float*)read_value(input_data, index, attr_id, offsets, num_of_attributes); 
     float f = *p; 
     f += 10; 
     //*p += 10; // not working on GPU 
    } 
    else if (types[attr_id] == 'i') { // if int 
     global int *p; 
     p = (global int*)read_value(input_data, index, attr_id, offsets, num_of_attributes); 
     int i = *p; 
     i += 10; 
     //*p += 10; 
    } 
    else { // if char 
     write_value(input_data, index, read_value(input_data, index, attr_id, offsets, num_of_attributes), attr_id, offsets, num_of_attributes); 
    } 
} 

それは10に増加しているテーブルのタプル、整数および浮動小数点の値を更新し、CHARフィールドがちょうど同じ内容に置き換えられます:ここで

はカーネルです。

+0

この問題が解決しない場合は、より包括的なソースコードを投稿してください。 – pmdj

+0

完全なカーネルのコードを追加しました。 – vgeclair

+1

このデータの整列状況はどうですか? floatとintベースの項目は4バイトの境界に揃えられていますか?そうでない場合、これが問題の原因になる可能性があります。 – pmdj

答えて

0

char配列のint値とfloat値が4バイト境界ではないため、この問題が発生することが判明しました。

offset = data + tuple_pos*4; // or 8, 16 etc 

などのアドレス宛てに書き込みを行っていると、すべて正常に動作します。

offset = data + tuple_pos*3; // or any other number not divisible by 4 

これは私が全体のデザインを変更し、何とかそれ以外の値を格納、またはint型を作るためにchar配列に「空」バイトを追加し、値に4つのバイトをフロートすべきいずれかのことを意味します。ただし、次のエラーが発生します(これは本当に良い解決策ではありません)。

1

byte_addressable_store extensionを有効にしていますか?あなたがこれを有効にしない限り、私が知っている限り、グローバルメモリへのバイト書き込みはOpenCLで明確に定義されていません。 (拡張機能が実装によってサポートされているかどうかを確認する必要があります)

カーネル引数に "正しい"タイプを使用することを検討することもできます。型が動的に変化する可能性がある場合は、おそらくunion型(またはstruct型の共用体フィールド)を試してみてください。

+0

申し訳ありませんが、私はあなたの返信を気付かなかった! cl_khr_byte_addressable_storeを追加しようとしましたが、問題はそのまま残ります。 – vgeclair