スポンサーリンク

VC++のプロジェクトにCUDAの.cuファイルが混在しているものをビルドする

VC++で、.cpp と .cuファイルが混在したプロジェクトのビルド方法。

1.ビルドのカスタマイズ

プロジェクトを右クリックして、「ビルドの依存関係」→「ビルドのカスタマイズ」を選択。

使用できるビルド カスタマイズ ファイルの中から、 CUDA 12.1 をチェックして OK をクリックする。

 

2..cuファイルをビルドに含める

.cuファイルを右クリック → プロパティ → プロパティページ を開き、「全般」から以下を設定

・ビルドから除外 → いいえ

・項目の種類 → CUDA C/C++

サンプルコード

source.cpp

#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);
}

mycuda.cuh

#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);

mycuda.cu

#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;
    }
}

実行結果

参考

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


この記事のトラックバックURL: