#include <cuda_runtime.h>
#include <iostream>
#define DATA_SIZE 1024 * 1024 // 데이터 크기
#define CHUNK_SIZE 256 * 1024 // 버퍼 크기
__global__ void processKernel(float *data, int size) {
int idx = threadIdx.x + blockIdx.x * blockDim.x;
if (idx < size) {
data[idx] = data[idx] * 2.0f; // 간단한 계산
}
}
void doubleBufferingExample() {
// 전체 데이터를 할당
float *hostData = new float[DATA_SIZE];
for (int i = 0; i < DATA_SIZE; i++) {
hostData[i] = i * 1.0f;
}
// GPU 메모리 버퍼 2개 생성
float *devBuffer1, *devBuffer2;
cudaMalloc(&devBuffer1, CHUNK_SIZE * sizeof(float));
cudaMalloc(&devBuffer2, CHUNK_SIZE * sizeof(float));
// 스트림 2개 생성
cudaStream_t stream1, stream2;
cudaStreamCreate(&stream1);
cudaStreamCreate(&stream2);
// Double Buffering
int chunks = DATA_SIZE / CHUNK_SIZE;
for (int i = 0; i < chunks; i++) {
// 현재와 다음 스트림 선택
cudaStream_t currentStream = (i % 2 == 0) ? stream1 : stream2;
float *currentBuffer = (i % 2 == 0) ? devBuffer1 : devBuffer2;
// 데이터 복사: CPU -> GPU
cudaMemcpyAsync(currentBuffer, &hostData[i * CHUNK_SIZE], CHUNK_SIZE * sizeof(float),
cudaMemcpyHostToDevice, currentStream);
// 커널 실행
processKernel<<<(CHUNK_SIZE + 255) / 256, 256, 0, currentStream>>>(currentBuffer, CHUNK_SIZE);
// 데이터 복사: GPU -> CPU
cudaMemcpyAsync(&hostData[i * CHUNK_SIZE], currentBuffer, CHUNK_SIZE * sizeof(float),
cudaMemcpyDeviceToHost, currentStream);
}
// 스트림 동기화
cudaStreamSynchronize(stream1);
cudaStreamSynchronize(stream2);
// 결과 확인
for (int i = 0; i < 10; i++) {
std::cout << hostData[i] << " ";
}
std::cout << std::endl;
// 메모리 해제
delete[] hostData;
cudaFree(devBuffer1);
cudaFree(devBuffer2);
cudaStreamDestroy(stream1);
cudaStreamDestroy(stream2);
}
int main() {
doubleBufferingExample();
return 0;
}