非同期関数

FGA ライブラリ関数の中には、その内部で GPU による処理が開始された直後 (※1)、 その処理の完了を待たずに関数の呼び出し側へ制御を返す、非同期仕様の関数( 以下、非同期関数 )があります。 (※2)

複数の非同期関数を連続して呼び出した場合、内部で開始される GPU 処理はその呼び出しが行われた順番にシリアル化されます。
その為 通常では、呼び出す関数が非同期であるか否かを意識する必要はありません。

ただし非同期関数の処理時間を計測するような場合には、非同期関数の呼び出し前と呼び出し後のタイムスタンプを単純に 比較したのでは正確な処理時間を得ることが出来ないことに注意して下さい。

このような場合には fnFGA_synchronize() を用いて非同期関数の処理完了を待って下さい。

※1.
ここで使用している 「GPU による処理が開始された直後」 という表現は、具体的には 「内部で行う CUDA カーネルの呼び出しの直後」 を意味します。 よって上記表現は厳密にいうと 「GPU に対し処理の実行開始の指令を送った直後」 ということになります。
※2.
非同期仕様となる FGA ライブラリ関数のリファレンスでは、その関数が非同期関数であることが明記されます。
処理時間測定例:
// サンプルである為、エラー処理等は省略していることに注意して下さい.

// またここでは時間取得の為に C 標準ライブラリ clock() を使用していますが、
// 実際に時間取得を行う際にはその環境で用意されているより精度の高い方法を
// 使用して下さい。

#include <time.h>
#include "fie.h"
#include "fga.h"


// === 間違った処理時間の計測例. ===
DOUBLE BAD_TimeCounter( FHANDLE src_FGA, FHANDLE dst_FGA )
{
    clock_t start, end;

    // 開始時間取得.
    start = clock();

    // 計測対象となる処理の実行.
    fnFGA_average( src_FGA, dst_FGA, F_BORDER_NONE, 0 );

    // 終了時間取得.
    //   しかし、fnFGA_average() は非同期関数である為、内部で GPU 処理を開始させた直後に制御を返す.
    //   おそらくこの時点で GPU 処理は完了しておらず、正しい処理時間は得られない.
    end = clock();

    return (DOUBLE)(end - start) / CLOCKS_PER_SEC;
}


// === 正しい処理時間の計測例. (その 1). ===
DOUBLE GOOD_TimeCounter_1( FHANDLE src_FGA, FHANDLE dst_FGA )
{
    clock_t start, end;

    // 他の GPU 処理が完了するのを待つ.
    fnFGA_synchronize();

    // 開始時間取得.
    start = clock();

    // 計測対象となる処理の実行.
    fnFGA_average( src_FGA, dst_FGA, F_BORDER_NONE, 0 );

    // 非同期関数 fnFGA_average() 内部での GPU 処理が完了するのを待つ.
    fnFGA_synchronize();

    // 終了時間取得.
    end = clock();

    return (DOUBLE)(end - start) / CLOCKS_PER_SEC;
}


// === 正しい処理時間の計測例. (その 2). ===
DOUBLE GOOD_TimeCounter_2( FHANDLE src_FGA )
{
    clock_t start, end;
    DOUBLE ave;

    // 他の GPU 処理が完了するのを待つ.
    fnFGA_synchronize();

    // 開始時間取得.
    start = clock();

    // 計測対象となる処理の実行.
    fnFGA_img_calc_average( src_FGA, &ave );

    // 終了時間取得.
    //   fnFGA_img_calc_average() は非同期関数ではない為、処理が完全に完了した後で制御を返す.
    //   その為、ここでは fnFGA_synchronize() による同期を行う必要はない.
    end = clock();

    return (DOUBLE)(end - start) / CLOCKS_PER_SEC;
}



VOID TimeCounter( VOID )
{
    FHANDLE src_FGA = NULL;
    FHANDLE dst_FGA = NULL;

    INT width = 4096, height = 4096;
    DOUBLE time;

    src_FGA = fnFGA_img_root_alloc( F_IMG_UC8, 1, width, height );
    dst_FGA = fnFGA_img_root_alloc( F_IMG_UC8, 1, width, height );

    // 間違った処理時間の計測例.
    time = BAD_TimeCounter( src_FGA, dst_FGA );

    // 正しい処理時間の計測例. (その 1).
    time = GOOD_TimeCounter_1( src_FGA, dst_FGA );

    // 正しい処理時間の計測例. (その 2).
    time = GOOD_TimeCounter_2( src_FGA );

    fnFIE_free_object( src_FGA );
    fnFIE_free_object( dst_FGA );
}

Documentation copyright © 2011 FAST Corporation. [B-002483]
Generated on Thu May 20 10:57:53 2021 for FGA ライブラリ by doxygen 1.5.6-FASTSP-p2