CudaによるMATLABプログラムの加速


CudaによるMATLABプログラムの加速
  • cuda加速MATLABプログラム
  • 1参考木子超の方法
  • 2参考Tomheavenの方法
  • 3引用
  • 最近はテンソルのモダリティ積を作るので、cudaを使って並列プログラミングをすることを考えていますが、c++は本当に面倒で、特にMATLABがあるときは、c++を書くのはまるで「時間の無駄」な行為です.MATLABでcudaのプログラムを呼び出すことができたら、どんなに素晴らしいことだろう.確かに、このことはとてもすばらしいですが、開発環境を配置する過程はとても苦痛で、私はこの問題を解決するのに1週間近くかかりました.読者が本文を読んでから貴重な時間を節約することを望んでいます.もしあなたがバージョンの比較的古いVS(例えば2005)とmatlabを使っているならば、この問題は実はとてもやりやすくて、nvmex関数を呼び出すだけでいいですが、stackoverflowのネットユーザーによると、MATLAB 2010 aからnvmexはサポートされていないので、ネット上ではnvmex関数をどのように変更してより高いバージョンのMATLABで実行できるかを議論する答えがたくさんあります.しかし、私は多くのソースコードを試しても成功しなかったので、あきらめました.幸いMATLABは比較的に新しいMATLABR 2015 bのバージョンを出して、このバージョンはmexcuda関数があって、使うのがとても心地よくて、1、2つのコードだけで呼び出すことができます.Cuプログラム、唯一の不足は、転送された配列がGPUARrayの形式でなければならないことであり、MATLABを再ダウンロードして再インストールするのも気分が悪い.もう一つ注意したいのはmathworksのreleasenoteにどのバージョンのMATLABがどのバージョンのcudaをサポートしているかということです.だからリロードなんて絶対に一番いい方法じゃないよ.次の2つの解決策を示します.
    1、木子超を参考にする方法
    この方法はとても完璧に书いてとても详しくて、私が出会った问题は彼が出会った问题とほとんど同じで、読者は対照的にすればいいので、私は自分でテストしたことがあって、テスト环境はMATLAB_ですR2014a+VS2010+cuda7.5.もう一つ注意すべきことは、木子超が与えたコードには少し欠陥があり、読者自身の改善が必要であることだ.ここでは言わない.以下にリンクを示します.http://blog.csdn.net/endlch/article/details/44561535
    2、Tomheavenの方法を参考にする
    この方法は私も自分でテストしたことがあります.テスト環境と同じように、著者はとてもよく書いています.小さな細部に注意しなければなりません.
    COMPFLAGS="-gencode=arch=compute_20,code=sm_20 -gencode=arch=compute_30,code=sm_30 -gencode=arch=compute_50,code=\"sm_50,compute_50\" --compiler-options=/c,/GR,/W3,/EHs,/nologo,/MD"

    上のこの場所でcuda 7なら5のバージョンでは、最初の行の最初のarchとcodeの後ろの数字を20に変更しなければなりません(cuda 5.5という数字は13だったのを覚えています).そうしないと、nvccのエラーが発生します.つまり、私が最初に言ったMATLABがサポートしているコンパイラのアーキテクチャが見つからないという問題があります.以下にリンクを示します.http://blog.csdn.net/hanlin_tan/article/details/48790273%%%%%%%%%%%%%%%%%%2018年更新%%%%%%%%%%%%以上MATLAB 2014でどのように配置するかについて述べていますが、2018年になると、Mathwork社はすでに深い学習の熱さとCuda+MATLAB開発環境の配置の苦痛を意識している可能性があります.したがって、最新バージョンのMATLAB(私の知っているMATLAB 2016 a以降のバージョン)は、新しい文「mexcuda」を定義しています.この文はとても便利です.例えば、ベクトル加算プログラム(VectorAdd.cu)があります.C++mexファイルをコンパイルする方法でコンパイルすればいいです.mexcuda VectorAdd.Cu、ちょっと待って、あなたが望む実行可能なファイルを生成することができます.MATLAB公式はテンプレートを与えていることに注意してくださいが、実際にはそれが与えた関数伝達方法に従ってGPUARrayを定義する必要はありません.伝統的なmex方法は依然として実行できます.皆さんの理解を容易にするために、以下の例を示します.
    
    #include "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\cuda_runtime.h"
    #include "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v7.5\include\device_launch_parameters.h"
    #include 
    #include 
    
    cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size);
    
    __global__ void addKernel(int *c, const int *a, const int *b)
    {
        int i = threadIdx.x;
        c[i] = a[i] + b[i];
    }
    
    
    void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
    {
        // initialize
        int *array_A = (int*)mxGetPr(prhs[0]);
        int *array_b = (int*)mxGetPr(prhs[1]);
        const int arraySize = 5;
        int c[arraySize] = { 0 };
    
           // Add vectors in parallel.
        cudaError_t cudaStatus = addWithCuda(c, array_A, array_b, arraySize);
        if (cudaStatus != cudaSuccess) {
            fprintf(stderr, "addWithCuda failed!");
        }
    
        printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}
    "
    , c[0], c[1], c[2], c[3], c[4]); // cudaDeviceReset must be called before exiting in order for profiling and // tracing tools such as Nsight and Visual Profiler to show complete traces. cudaStatus = cudaDeviceReset(); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaDeviceReset failed!"); } } // Helper function for using CUDA to add vectors in parallel. cudaError_t addWithCuda(int *c, const int *a, const int *b, unsigned int size) { int *dev_a = 0; int *dev_b = 0; int *dev_c = 0; cudaError_t cudaStatus; // Choose which GPU to run on, change this on a multi-GPU system. cudaStatus = cudaSetDevice(0); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaSetDevice failed! Do you have a CUDA-capable GPU installed?"); goto Error; } // Allocate GPU buffers for three vectors (two input, one output) . cudaStatus = cudaMalloc((void**)&dev_c, size * sizeof(int)); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMalloc failed!"); goto Error; } cudaStatus = cudaMalloc((void**)&dev_a, size * sizeof(int)); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMalloc failed!"); goto Error; } cudaStatus = cudaMalloc((void**)&dev_b, size * sizeof(int)); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMalloc failed!"); goto Error; } // Copy input vectors from host memory to GPU buffers. cudaStatus = cudaMemcpy(dev_a, a, size * sizeof(int), cudaMemcpyHostToDevice); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMemcpy failed!"); goto Error; } cudaStatus = cudaMemcpy(dev_b, b, size * sizeof(int), cudaMemcpyHostToDevice); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMemcpy failed!"); goto Error; } // Launch a kernel on the GPU with one thread for each element. addKernel<<<1, size>>>(dev_c, dev_a, dev_b); // Check for any errors launching the kernel cudaStatus = cudaGetLastError(); if (cudaStatus != cudaSuccess) { fprintf(stderr, "addKernel launch failed: %s
    "
    , cudaGetErrorString(cudaStatus)); goto Error; } // cudaDeviceSynchronize waits for the kernel to finish, and returns // any errors encountered during the launch. cudaStatus = cudaDeviceSynchronize(); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaDeviceSynchronize returned error code %d after launching addKernel!
    "
    , cudaStatus); goto Error; } // Copy output vector from GPU buffer to host memory. cudaStatus = cudaMemcpy(c, dev_c, size * sizeof(int), cudaMemcpyDeviceToHost); if (cudaStatus != cudaSuccess) { fprintf(stderr, "cudaMemcpy failed!"); goto Error; } Error: cudaFree(dev_c); cudaFree(dev_a); cudaFree(dev_b); return cudaStatus; }

    最初の2行は対応するCudaインストールディレクトリに対応していることに注意してください.もしあなたが管理するのがおっくうであれば、Cudaをインストールするときにクリックして確定すればいいです.
    もう一つの問題は、皆さんが気づいたと思います.それはバージョンの問題です.私の知っている限りでは、Cudaは9.1まで出ていますが、MATLABはまだ一定の遅れがあります.しかし、私たちは一生Cuda 7を使うことはできません.5とVS 2012、私はMathworkの公式フォーラムとStackoverflowで以下を検索して、以下のネットユーザーの返事を得ました:
    参照ブロック内容This is how to compile(mexcuda)with Visual Studio 2015 and Cuda 8.0:1:Go to:「toolboxdistcompgpuexternsrc mexwin 64」2:Copy files and rename 2013 to 2015:{"nvcc_msvcpp2013.xml","nvcc_msvcpp2013_dynamic.xml"}3:Replace inside those files"7.5"to"8.0"and"12"to"14"14"to"14"14"14"14"to"14"14".4:Done.
    今日は実験以下ですが、成功したら、また更新します.
    3、引用
    [1]: http://blog.csdn.net/endlch/article/details/44561535 [2]: http://blog.csdn.net/hanlin_tan/article/details/48790273