インテル® C++ コンパイラー 18.0 デベロッパー・ガイドおよびリファレンス
ここでは、非同期 I/O を使用した場合と同期 I/O を使用した場合のパフォーマンスの違いを示します。次の例は、メインプログラムで 2 つのベクトルのスカラー乗算を正規化し、5.6 MB のデータを非同期に書き込みます。
スカラー乗算を実行する C ソースファイル:
#include <math.h> #include <stdio.h> #include <stdlib.h> double do_compute(double A, double B, int arr_len) { int i; double res = 0; double *xA = malloc(arr_len * sizeof(double)); double *xB = malloc(arr_len * sizeof(double)); if ( !xA || !xB ) abort(); for (i = 0; i < arr_len; i++) { xA[i] = sin(A); xB[i] = cos(B); res = res + xA[i]*xA[i]; } free(xA); free(xB); return res; }
非同期 I/O を使用する C メイン・ソース・ファイル:
#define DIM_X 123/*123*/ #define DIM_Y 70000 double aio_dat[DIM_Y /*12MB*/] = {0}; double aio_dat_tmp[DIM_Y /*12MB*/]; #include <stdio.h> #include <aio.h> typedef struct aiocb aiocb_t; aiocb_t my_aio; aiocb_t *my_aio_list[1] = {&my_aio}; int main() { double do_compute(double A, double B, int arr_len); int i, j; HANDLE fd = CreateFile("aio.dat", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); /* 複雑な計算を実行 */ for (i = 0; i < DIM_X; i++) { for ( j = 0; j < DIM_Y; j++ ) aio_dat[j] = do_compute(i, j, DIM_X); if (i) aio_suspend(my_aio_list, 1, 0); my_aio.aio_fildes = fd; my_aio.aio_buf = memcpy(aio_dat_tmp, aio_dat, sizeof(aio_dat_tmp)); my_aio.aio_nbytes = sizeof(aio_dat_tmp); my_aio.aio_offset = (intptr_t)-1; my_aio.aio_sigevent.sigev_notify = SIGEV_NONE; if ( aio_write((void*)&my_aio) == -1 ) { printf("ERROR!!! %s\n", "aio_write()==-1"); abort();} } aio_suspend(my_aio_list, 1, 0); return 0; }
非同期 I/O を使用する C メイン・ソース・ファイル例 2:
// icl -c do_compute.c // icl aio_sample2.c do_compute.obj // aio_sample2.exe #define DIM_X 123 #define DIM_Y 70 double aio_dat[DIM_Y] = {0}; double aio_dat_tmp[DIM_Y]; static volatile int aio_flg = 1; #include <aio.h> typedef struct aiocb aiocb_t; aiocb_t my_aio; #define WAIT { while (!aio_flg); aio_flg = 0; } #define aio_OPEN(_fname )\ CreateFile(_fname, \ GENERIC_READ | GENERIC_WRITE, \ FILE_SHARE_READ, \ NULL, \ OPEN_ALWAYS, \ FILE_ATTRIBUTE_NORMAL, \ NULL) static void aio_CompletionRoutine(sigval_t sigval) { aio_flg = 1; } int main() { double do_compute(double A, double B, int arr_len); int i, j, res; char *fname = "aio_sample2.dat"; HANDLE aio_fildes = aio_OPEN(fname); my_aio.aio_fildes = aio_fildes; my_aio.aio_nbytes = sizeof(aio_dat_tmp); my_aio.aio_sigevent.sigev_notify = SIGEV_THREAD; my_aio.aio_sigevent.sigev_notify_function = aio_CompletionRoutine; /* ** 書き込み中 */ my_aio.aio_offset = -1; printf("Writing\n"); for (i = 0; i < DIM_X; i++) { for (j = 0; j < DIM_Y; j++) aio_dat[j] = do_compute(i, j, DIM_X); WAIT; my_aio.aio_buf = memcpy(aio_dat_tmp, aio_dat, sizeof(aio_dat_tmp)); res = aio_write(&my_aio); if (res) {printf("res!=0\n");abort();} } // // フラッシュ中 // printf("Flushing\n"); WAIT; res = aio_fsync(O_SYNC, &my_aio); if (res) {printf("res!=0\n");abort();} WAIT; // // 読み取り中 // printf("Reading\n"); my_aio.aio_offset = 0; my_aio.aio_buf = (volatile char*)aio_dat_tmp; for (i = 0; i < DIM_X; i++) { aio_read(&my_aio); for (j = 0; j < DIM_Y; j++) aio_dat[j] = do_compute(i, j, DIM_X); WAIT; res = aio_return(&my_aio); if (res != sizeof(aio_dat)) { printf("aio_read() did read %d bytes, expecting %d bytes\n", res, sizeof(aio_dat)); } for (j = 0; j < DIM_Y; j++) if ( aio_dat[j] != aio_dat_tmp[j] ) {printf("ERROR: aio_dat[j] != aio_dat_tmp[j]\n I=%d J=%d\n", i, j); abort();} my_aio.aio_offset += my_aio.aio_nbytes; } CloseHandle(aio_fildes); printf("\nDone\n"); return 0; }