아직 코드 연구중인 부분입니다.....
기준 VS2017
- 새 프로젝트를 생성한다.
- Visual C++ → Windows 데스크톱 → DLL(동적 연결 라이브러리)
- 구성 관리자에 프로젝트 타겟 설정 변경
- 자신이 설계하고자 하는 목적에 맞게 구성 (Debug, Release 등) 및 플랫폼 (x86, x64 등)을 설정한다.
- 프로젝트의 빌드설정을 변경한다.
- 프로젝트 우클릭 → 빌드 종속성 → 사용자 지정 빌드
- 자신의 버전에 맞는 CUDA를 체크한다.
- 현재 자신의 CUDA 설정 확인해볼 것!
- 프로젝트의 빌드 순서를 변경한다.
- 프로젝트 우클릭 → 빌드 종속성 → 프로젝트 종속성 또는 프로젝트 빌드 순서
- DLL을 생성하는 프로젝트가 DLL을 사용하는 프로젝트 보다 먼저 빌드되어야 한다.
- 생성한 프로젝트의 속성 페이지로 진입한다.
- 생성한 프로젝트 우클릭 → 속성
- 구성속성 → 일반
- 관리되는 증분 빌드 사용 : 예 ← 공용 언어 런타임 지원 옵션을 변경하면 자동으로 바뀜
- 구성 형식 : 동적 라이브러리 (.dll)
- 문자 집합 : 자유
- 공용 언어 런타임 지원 : 공용 언어 런타임 지원 (/clr) ← 중요!!
- .NET 대상 프레임워크 버전 : 사용할 C#의 .NET 버전에 맞게 입력
- 구성속성 → C/C++
- 일반
- 추가 포함 디렉터리 : $(CudaToolkitIncludeDir)
- 미리 컴파일된 헤더
- 미리 컴파일된 헤더 : 미리 컴파일된 헤더 사용 안 함 ← 사용을 해도 무방할 듯
- 구성속성 → CUDA C/C++
- Common
- Target Machine Platform : 플랫폼 버전에 맞게 변경
- 구성속성 → 링커
- 일반
- 추가 라이브러리 디렉터리 : $(CudaToolkitLibDir)
- 입력
- 추가 종속성 : cudart_static.lib;
- 생성한 프로젝트의 참조 파일을 추가한다.
- 프로젝트 하위 트링에 "참조" 부분 우클릭 → 참조 추가
- 어셈블리 부분에서 "mscorlib" 파일을 찾아서 체크
- CUDA 코드 속성
- 코드 파일의 속성 페이지로 진입한다.
- "일반 → 항목 형식" 부분이 CUDA C/C++ 로 설정되어 있는지 확인
- 닷넷 프로젝트에 참조 추가
- 사용하려는 닷넷(C#) 프로젝트의 "참조"에 CUDA C++/CLI 프로젝트를 추가한다.
※ 코드 예시
<C++/CLI 헤더 부분>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #pragma once #include <stdio.h> #include <windows.h> #include <iostream> using namespace System; using namespace System::Runtime::InteropServices; namespace ManagedCu { public ref class MyCudaCliWrap { public: MyCudaCliWrap(); ~MyCudaCliWrap(); void RunAdd(cli::array<int> ^c, cli::array<int> ^a, cli::array<int> ^b, int size); }; } | cs |
<C++/CLI 코드 부분>
주의 사항!
nvcc는 C++/CLI의 문법을 인식하지 못한다고함.
따라서 <<<grid,block>>>() 부분을 cudaLaunchKernel()로 바꾸어야 한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | #include "MyCudaCliWrapper.h" #include "MyCliKernel.cuh" #include "cuda_runtime.h" #include "device_launch_parameters.h" namespace ManagedCu { MyCudaCliWrap::MyCudaCliWrap() { } MyCudaCliWrap::~MyCudaCliWrap() { } void MyCudaCliWrap::RunAdd(cli::array<int> ^c, cli::array<int> ^a, cli::array<int> ^b, int size) { //extern void addKernel(int* c, int const* a, const int* b); pin_ptr<int> pin_a = &a[0]; pin_ptr<int> pin_b = &b[0]; pin_ptr<int> pin_c = &c[0]; int *p_a = pin_a; int *p_b = pin_b; int *p_c = pin_c; int* dev_a = 0; int* dev_b = 0; int* dev_c = 0; cudaError_t cudaStatus; cudaStatus = cudaSetDevice(0); cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int)); cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int)); cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int)); cudaStatus = cudaMemcpy(dev_a, p_a, size * sizeof(int), cudaMemcpyHostToDevice); cudaStatus = cudaMemcpy(dev_b, p_b, size * sizeof(int), cudaMemcpyHostToDevice); void* args[] = { &dev_c, &dev_a, &dev_b }; cudaLaunchKernel( (const void*)&addKernel, // pointer to kernel func. dim3(1), // grid dim3(size), // block args // arguments ); cudaStatus = cudaDeviceSynchronize(); cudaStatus = cudaMemcpy(p_c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost); cudaFree(dev_c); cudaFree(dev_a); cudaFree(dev_b); } } | cs |
<CUDA 코드>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | //////////////////////////////////////////////////////////////// //Cuda 헤더 부분// #pragma once #include "cuda_runtime.h" #include "device_launch_parameters.h" __global__ void addKernel(int *c, int const* a, int const* b); ///////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////// //Cuda 코드 부분// #include "MyCliKernel.cuh" #include "cuda_runtime.h" #include "device_launch_parameters.h" __global__ void addKernel(int *c, int const* a, int const* b) { int i = threadIdx.x; c[i] = a[i] + b[i]; } ////////////////////////////////////////////////////////////////// | cs |
<C#에서 이런 식으로 받아 쓰면 된다>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | private void BtnRun3_Click(object sender, RoutedEventArgs e) { try { int[] a = { 1, 2, 3, 4, 5 }; int[] b = { 110, 220, 330, 440, 550 }; int[] c = new int[5]; ManagedCu.MyCudaCliWrap obj = new ManagedCu.MyCudaCliWrap(); obj.RunAdd(c, a, b, 5); foreach (int i in c) { System.Console.Write("{0} ", i); } Console.WriteLine(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } | cs |
참고
http://www.orangeowlsolutions.com/archives/199
https://qiita.com/episteme/items/55b321cec427048d0c0c
https://gist.github.com/parsa/aff600b60b1410d252f6192e797f287d
https://diehard98.tistory.com/entry/Quick-CCLI-Learn-CCLI-in-less-than-10-minutes
http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=51&MAEULNO=20&no=8283
https://huiyu.tistory.com/entry/CCLI-%EA%B8%B0%EB%B3%B8-%EC%98%88%EC%A0%9C
https://andromedarabbit.net/cplusplus_cli_lecture_2009_01/
https://six605.tistory.com/391
'Study > CUDA' 카테고리의 다른 글
CUDA를 C#에서 사용해보자 (2) | 2019.07.08 |
---|---|
CUDA (0) | 2019.02.20 |