1

符号なし 8 ビット整数のファイルを (バイナリ形式で) 読み込んでいます。これを float の配列に変換する必要があります。通常、私は次のようなことをするだけです:

uint8_t *s1_tmp = (uint8_t *)malloc(sizeof(uint8_t)*num_elements);
float *s1 = (float *)malloc(sizeof(float)*num_elements);

fread(s1_tmp, sizeof(uint8_t), num_elements, file_id);

for(int i = 0; i < num_elements; i++){
    s1[i] = s1_tmp[i];
}

free(s1_tmp)

確かに刺激を受けていませんが、うまくいきます。ただし、現在num_elementsは約 270 万であるため、プロセスは非常に遅く、IMO では無駄です。

8 ビット整数を float として読み込むか、uint8_t配列を float 配列に変換するより良い方法はありますか?

4

1 に答える 1

5

第一に、これはデータの読み込みによる I/O バウンドになります。第二に、メモリバウンドになります。変換と読み取りをインターリーブすると、キャッシュのパフォーマンスが大幅に向上します。

良好な I/O パフォーマンスを得るには十分な大きさで、キャッシュに収まる程度には十分小さい妥当なバッファ サイズを選択してください。おそらく 8 ~ 32 KB 程度です。それだけのデータを読み込んで、変換して、繰り返します。

例えば:

#define BUFSIZE 16384
uint8_t *buffer = malloc(BUFSIZE);
float *s1 = malloc(num_elements * sizeof(float));

int total_read = 0;
int n;
while(total_read < num_elements && (n = fread(buffer, 1, BUFSIZE, file_id)) > 0)
{
    n = min(n, num_elements - total_read);
    for(int i = 0; i < n; i++)
        s1[total_read + i] = (float)buffer[i];
    total_read += n;
}
free(buffer);

また、SIMD 演算を使用して複数の項目を一度に変換すると、パフォーマンスが向上する場合もあります。ただし、全体のパフォーマンスは fread からの I/O によって依然としてボトルネックとなるため、SIMD からどの程度の改善が見られるかは疑問です。

多数のuint8_t値を変換しているため、整数から浮動小数点への変換を行う代わりにルックアップ テーブルを使用することで、パフォーマンスが向上する可能性があります。必要なのは、キャッシュに簡単に収まる 256 個の float 値 (1 KB) のルックアップ テーブルだけです。それがより速いかどうかはわかりませんので、コードをプロファイリングして、最適なオプションが何であるかを判断する必要があります。

于 2012-09-26T15:34:47.277 に答える