VC++で、.cpp と .cuファイルが混在したプロジェクトのビルド方法。
プロジェクトを右クリックして、「ビルドの依存関係」→「ビルドのカスタマイズ」を選択。
使用できるビルド カスタマイズ ファイルの中から、 CUDA 12.1 をチェックして OK をクリックする。
.cuファイルを右クリック → プロパティ → プロパティページ を開き、「全般」から以下を設定
・ビルドから除外 → いいえ
・項目の種類 → CUDA C/C++
#include <windows.h> #include <memory> #include "mycuda.cuh" #pragma warning(disable:4996) void pnmP3_Write(const char* const fname, const int width, const int height, const unsigned char* const p); static const int N = 500;//作成画像 N × N LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) { static std::unique_ptr<unsigned char[]> p_cpu; switch (msg) { case WM_DESTROY: PostQuitMessage(0); return 0; case WM_CREATE: p_cpu.reset(new unsigned char[N * N * 3]); call_mycuda(N, p_cpu.get()); return 0; case WM_PAINT: { // dc設定 PAINTSTRUCT ps; HDC hdc = BeginPaint(hwnd, &ps); for(int x=0;x<N;x++) for (int y = 0; y < N; y++) { size_t pos = N * y + x;//二次元座標を一次元座標に SetPixel(hdc, x, y, RGB( p_cpu[pos * 3 + 0], p_cpu[pos * 3 + 1], p_cpu[pos * 3 + 2] ) ); } EndPaint(hwnd, &ps); } } return DefWindowProc(hwnd, msg, wp, lp); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow) { HWND hwnd; MSG msg; WNDCLASS winc; winc.style = CS_HREDRAW | CS_VREDRAW; winc.lpfnWndProc = WndProc; winc.cbClsExtra = winc.cbWndExtra = 0; winc.hInstance = hInstance; winc.hIcon = LoadIcon(NULL, IDI_APPLICATION); winc.hCursor = LoadCursor(NULL, IDC_ARROW); winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); winc.lpszMenuName = NULL; winc.lpszClassName = TEXT("SZL-WINDOW"); if (!RegisterClass(&winc)) return -1; hwnd = CreateWindow( TEXT("SZL-WINDOW"), TEXT("mywindow"), WS_OVERLAPPEDWINDOW | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, N+100, N+100, NULL, NULL, hInstance, NULL ); if (hwnd == NULL) return -1; while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg); return msg.wParam; } ///////////////////////////////////////////// //画像ファイル書き出し///////////////////////// //! @brief PPM(RGB各1byte,カラー,テキスト)を書き込む //! @param [in] fname ファイル名 //! @param [in] width 画像の幅 //! @param [in] height 画像の高さ //! @param [in] p 画像のメモリへのアドレス //! @details RGBRGBRGB....のメモリを渡すと、RGBテキストでファイル名fnameで書き込む void pnmP3_Write(const char* const fname, const int width, const int height, const unsigned char* const p) { // PPM ASCII FILE* fp = fopen(fname, "wb"); fprintf(fp, "P3\n%d %d\n%d\n", width, height, 255); size_t k = 0; for (size_t i = 0; i < (size_t)height; i++) { for (size_t j = 0; j < (size_t)width; j++) { fprintf(fp, "%d %d %d ", p[k * 3 + 0], p[k * 3 + 1], p[k * 3 + 2]); k++; } fprintf(fp, "\n"); } fclose(fp); }
#include <stdio.h> #include <cstring> #include <cuda_runtime.h> void call_mycuda(const int N, unsigned char* p_cpu); /////////////////////////////////////////////// // GPU側 ////////////////////////////////////// __global__ void gradation(unsigned char* c, const int N);
#include "mycuda.cuh" #include <device_launch_parameters.h> #pragma comment(lib,"cudart.lib") #pragma comment(lib,"cuda.lib") void call_mycuda(const int N, unsigned char* p_cpu) { //作成画像 N × N × 3 //16×16の領域に分けて計算する dim3 block(16, 16); //グリッド数 dim3 grid(N / 16 + 1, N / 16 + 1); unsigned char* p_gpu;//GPU側メモリ確保 cudaMalloc((void**)&p_gpu, N * N * 3); gradation << <grid, block >> > (p_gpu, N); //GPU→CPU側へメモリコピー cudaMemcpy(p_cpu, p_gpu, N * N * 3, cudaMemcpyDeviceToHost); cudaFree(p_gpu); } __global__ void gradation(unsigned char* c, const int N) { //アクセス法 //このスレッドが担当する画素の位置を二次元座標で求める size_t xpos = blockIdx.x * blockDim.x + threadIdx.x; size_t ypos = blockIdx.y * blockDim.y + threadIdx.y; if (xpos < N && ypos < N) { size_t pos = N * ypos + xpos;//二次元座標を一次元座標に float R = ypos / (float)N; float G = (N - ypos) / (float)N; float B = xpos / (float)N; c[pos * 3 + 0] = R * 255;//0~255にして色書き込み c[pos * 3 + 1] = G * 255; c[pos * 3 + 2] = B * 255; } }