본문 바로가기

Linux

Asynchronous IO Read (Direct I/O)

#define _GNU_SOURCE
#include <aio.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <cuda.h>
#include <cuda_runtime_api.h>

void main() {
    char *path="file.txt"; // file path
    int flag = O_RDWR | O_DIRECT; // direct i/o flag
    mode_t mode = 0644;
    int fd = open(path, flag, mode); // open file with direct i/o
    if(fd == -1) fprintf(stderr, "Can't Open!!\n");
    int ret, err;

    float *buf;
    int buf_size = 2048*sizeof(float);
    struct aiocb c_aio[10];
//    posix_memalign(&buf, 512,buf_size); // buffer space allocation (1) posix_memalign
//    buf = (float *)malloc(buf_size); // buffer space allocation (2) malloc
    cudaMallocManaged(&buf, buf_size, cudaMemAttachHost); // buffer space allocation (3) use Unified Memory

    for(int i=0; i<10; i++) { // if use multi aio_read
        bzero((float*)&c_aio[i], sizeof(struct aiocb)); // init aiocb
        c_aio[i].aio_fildes = fd; // AIO read/write dir
        c_aio[i].aio_buf = buf; // AIO buffer
//        posix_memalign(&c_aio[i].aio_buf, 512,buf_size); // AIO buffer
        if(!c_aio[i].aio_buf) perror("buffer allocation\n");
        c_aio[i].aio_offset = 0; // AIO file offset
    }

    if (fd != -1)
    {
        printf("check\n");
        printf("1.\n"); // first AIO read call
        c_aio[0].aio_nbytes = 1024; // AIO read bytes (n*512 bytes)
        aio_read(&c_aio[0]); // AIO read
        ret = aio_return(&c_aio[0]); // check read size (return read_size or fail(-1))
//        printf("%d\n", ret);

        c_aio[1].aio_offset += 2048; // move file offset
        c_aio[1].aio_buf += 1024; // move buffer addr
        
        printf("2.\n"); // second AIO read call
        c_aio[1].aio_nbytes = 1024;
        aio_read(&c_aio[1]); // AIO read
        while(1){ // which one ends sooner (aio[0] or aio[1])
            if(aio_error(&c_aio[0]) == EINPROGRESS){
                printf("0");
            }
            if(aio_error(&c_aio[1]) == EINPROGRESS){
                printf("1");
            }
            if(aio_error(&c_aio[0]) != EINPROGRESS || aio_error(&c_aio[1]) != EINPROGRESS){
                break;
            }
        }
//        while(aio_error(&c_aio[0]) == EINPROGRESS) printf("In Progress 1\n"); // just aio[0] synchronization
        printf("buffer \n %s\n", buf); // current buffer state
	}
    close(fd); // close file
}

 

#GCC Compile

gcc aio.c -o aio -lrt

#NVCC Compile

nvcc aio.c -o aio -lrt -L/usr/local/cuda/lib -lcuda