はじめに
64bit化したVisual Studio 2010 ExpressとCUDA7.5でGPGPUプログラムをコンパイルする方法をまとめた。
OS: Windows7SP1 64bit
VS: Visualt C++ 2010 Express + WindowsSDK7.1
CUDA: CUDA7.5
GPU: GeForce GT520
64bit化 Visual Studio 2010 Express のインストール
以前はダウンロードセンターから入手できたが、今は残念ながらリンクが切れている。今回は保存しておいたISOイメージを使用した。
※ 無料で登録できるVisual Studio Dev Essentialsにも2010はさすがに古いようで置いてなかった。
ISOイメージVS2010ExpressJPN.isoをVirtual CloneDriveなどでマウントしてインストーラSteup.htaを実行
ついでにVC#, VBもインストール
WindowsSDK7.1のインストール時にエラーが発生するので、次の2つのライブラリをアンインストール
- Microsoft Visual C++ 2010 x86 Redistributable
- Microsoft Visual C++ 2010 x64 Redistributable
WindowsSDK7.1のインストーラが.NET Framework 4.6.1を認識してくれないので、4.6.1をアンインストールして4.5.2をインストール
- Microsoft .NET Framework 4.6.1 →アンインストール
- Microsoft .NET Framework 4.5.2 →インストール
ISOイメージGRMSDKX_EN_DVD.isoをマウントしてインストーラsetup.exeを実行
Help Library ManagerはVisual C++など好きなものを入れておく
ISOイメージVS2010SP1dvd1.isoをマウントしてインストーラSetup.exeを実行
WindowsSDK7.1用Visual C++ 2010 SP1更新プログラムをダウンロードして適用
オフラインインストーラNDP462-KB3151800-x86-x64-AllOS-ENU.exeをダウンロードして実行
・Microsoft Visual C++ 2010 Expressを起動
・新しいプロジェクト→Win32コンソールアプリケーション
・ビルド→構成マネージャー→アクティブソリューションプラットフォーム→新規作成→x64
・プロジェクト→プロパティ→構成プロパティ→全般→プロットフォームツールセット→Windows7.1SDK
・サンプルコード
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0;
cout << "address size = " << sizeof(&a) << " bytes" << endl;
return 0;
}
・サンプルコードの実行
C:\...\x64\Debug> sample_64bit.exe
address size = 8 bytes
CUDA7.5のインストール
タウンロードページからGPUボードに合った最新のドライバ(今回は381.65-desktop-win8-win7-64bit-international-whql.exe)をダウンロードして実行
ダウンロードページのLegacy CUDA ToolkitsからCUDA Toolkit 7.5をダウンロードして実行
・カスタム
・次の3つのみインストール(他は最新のドライバでインストール済み)
CUDA Samples
CUDA Toolkit
CUDA Visual Studio Integration
・インストール場所はエクスプローラで事前に作成しておく
CUDA Toolkit: C:\USR\CUDA\v7.5
CUDA Samples: C:\USR\CUDA\v7.5\SDK
例としてdeviceQueryをコンパイル&実行
・次のソリューションファイルをVisual C++ 2010 Expressで起動
C:\USR\CUDA\v7.5\SDK\1_Utilities\deviceQuery\deviceQuery_vs2010.sln
・プロジェクト→プロパティ→構成プロパティ→全般→プロットフォームツールセット→Windows7.1SDK
・ビルドしてコマンドプロンプトから実行
C:\Users\myname> cd C:\USR\CUDA\v7.5\SDK\bin\win64\Debug
C:\...\Debug> deviceQuery.exe
deviceQuery.exe Starting...
CUDA Device Query (Runtime API) version (CUDART static linking)
Detected 1 CUDA Capable device(s)
Device 0: "GeForce GT 520"
CUDA Driver Version / Runtime Version 8.0 / 7.5
CUDA Capability Major/Minor version number: 2.1
(途中省略)
Result = PASS
新規プロジェクトでCUDAを使う
・Microsoft Visual C++ 2010 Expressを起動
・新しいプロジェクト→Win32コンソールアプリケーション
・ビルド→構成マネージャー→アクティブソリューションプラットフォーム→新規作成→x64
・プロジェクト→プロパティ→構成プロパティ→全般→プロットフォームツールセット→Windows7.1SDK
・プロジェクト→ビルドのカスタマイズ→CUDA7.5をチェック
・C/C++→追加のインクルードディレクトリ
./;$(CudaToolkitIncludeDir);$(CudaToolkitDir)/common/inc
・リンカー→追加のライブラリディレクトリ
$(CudaToolkitLibDir)
・リンカー→入力→追加の依存ファイル
cudart_static.lib
・サンプルコード
#include "stdafx.h"
#include <cuda_runtime.h>
#include <stdio.h>
#include <vector>
using namespace std;
void saxpyz(float a, vector<float>& x, vector<float>& y, vector<float>& z);
int main(int argc, char* argv[]) {
printf("%s starting...\n", argv[0]);
const int n = 10000;
vector<float> x(n, 0.0f);
vector<float> y(n, 0.0f);
vector<float> z(n, 0.0f);
for(int i = 0; i < n; ++i) {
x[i] = 0.2f;
y[i] = 0.4f;
z[i] = 0.0f;
}
const float a = 3.0f;
saxpyz(a, x, y, z);
float sum = 0.0f;
for(int i = 0; i < n; ++i) {
sum += z[i];
}
bool success = (sum - n)*(sum - n) < 0.1;
printf("n=%d, sum=%.0f, result=%s\n", n, sum, (success ? "OK" : "NG"));
return success ? 0 : 1;
}
#include <cuda.h>
#include <vector>
using namespace std;
__global__ void saxpyzKernel(int n, float a, float* x, float* y, float* z) {
int i = blockIdx.x*blockDim.x + threadIdx.x;
if(i < n) z[i] = a*x[i] + y[i];
}
void saxpyz(float a, vector<float>& x, vector<float>& y, vector<float>& z) {
float* x_d;
float* y_d;
float* z_d;
const int n = (int)z.size();
cudaMalloc((void**)&x_d, n*sizeof(float));
cudaMalloc((void**)&y_d, n*sizeof(float));
cudaMalloc((void**)&z_d, n*sizeof(float));
cudaMemcpy(x_d, &x[0], n*sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(y_d, &y[0], n*sizeof(float), cudaMemcpyHostToDevice);
const int blockSize = 256;
const int blockNum = (n + blockSize - 1)/blockSize;
saxpyzKernel<<<blockNum, blockSize>>>(n, a, x_d, y_d, z_d);
cudaDeviceSynchronize();
cudaMemcpy(&z[0], z_d, n*sizeof(float), cudaMemcpyDeviceToHost);
cudaFree(z_d);
cudaFree(y_d);
cudaFree(x_d);
}
・サンプルコードの実行
C:\...\x64\Release> sample_cuda.exe
sample_cuda.exe starting...
n=10000, sum=10000, result=OK