在C ++ / CLI和C#中调用cublas时出现意外结果

时间:2016-04-26 09:18:41

标签: c# c++11 cuda c++-cli cublas

我用Visual Studio编写了一个C ++ 11 / CLI包装器来使用CUDA的CuBLAS。我正在使用CUDA Toolkit 7.0。

以下是我的包装器的源代码:

#pragma once

#include "stdafx.h"
#include "BLAS.h"
#include "cuBLAS.h"

namespace lab
{
    namespace Mathematics
    {
        namespace CUDA
        {

            void BLAS::DAXPY(int n, double alpha, const array<double> ^x, int incx, array<double> ^y, int incy)
            {
                pin_ptr<double> xPtr = &(x[0]);
                pin_ptr<double> yPtr = &(y[0]);
                pin_ptr<double> alphaPtr = &alpha;

                cuBLAS::DAXPY(n, alphaPtr, xPtr, incx, yPtr, incy);
            }
       }
   }
}

为了测试这段代码,我在C#编写了以下测试:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Linq;
using lab.Mathematics.CUDA;

namespace lab.Mathematics.CUDA.Test
{
  [TestClass]
  public class TestBLAS
  {
    [TestMethod]
    public void TestDAXPY()
    {
        var count = 10;
        var alpha = 1.0;
        var a = Enumerable.Range(0, count).Select(x => Convert.ToDouble(x)).ToArray();
        var b = Enumerable.Range(0, count).Select(x => Convert.ToDouble(x)).ToArray();

        // Call CUDA
        BLAS.DAXPY(count, alpha, a, 1, b, 1);

        // Validate results
        for (int i = 0; i < count; i++)
        {
            Assert.AreEqual(i + i, b[i]);
        }
    }
  }
}

该程序使用x64架构进行编译,没有错误。但每次运行测试时,我得到的结果都不同。更准确地说,数组b是结果,每次都有不同的值。我不知道为什么。

我也在那里添加我的cuda代码,有人可以找到问题。请注意,我没有收到任何错误,在编译时会发出任何警告。我也想知道在编译过程中我可能需要做一些更改,而我什么也没做,并且使用了默认选项。

void cuBLAS::DAXPY(int n, const double *alpha, const double *x, int incx, double *y, int incy)
        {

            cudaError_t cudaStat;
            cublasStatus_t stat;

            // Allocate GPU memory
            double *devX, *devY;
            cudastat = cudaMalloc((void **)&devX, (size_t)n*sizeof(*devX));

            if (cudaStat != cudaSuccess) {
                // throw exception

                std::ostringstream msg;
                msg << "device memory allocation failed: fail.Stat = " << cudaStat;
                throw new std::exception(msg.str().c_str());
            }
            cudaMalloc((void **)&devY, (size_t)n*sizeof(*devY));

            // Create cuBLAS handle
            cublasHandle_t handle;
            cublasCreate(&handle);

            // Initialize the input matrix and vector
            cublasSetVector(n, sizeof(*devX), x, incx, devX, incx);
            cublasSetVector(n, sizeof(*devY), y, incy, devY, incy);

            // Call cuBLAS function
            cublasDaxpy(handle, n, alpha, devX, incx, devY, incy);

            // Retrieve resulting vector
            cublasGetVector(n, sizeof(*devY), devY, incy, y, incy);

            // Free GPU resources
            cudaFree(devX);
            cudaFree(devY);
            cublasDestroy(handle);
        }

编辑:我添加了David Yaw的新建议,并为所有cuda操作添加了错误检查。但由于可读性,我没有写这里的所有错误检查。仍然没有工作。

2 个答案:

答案 0 :(得分:2)

您的错误就在这些行中。

// Initialize the input matrix and vector
cublasSetVector(n, sizeof(*devX), x, incx, devX, incx);

// Call cuBLAS function
cublasDaxpy(handle, n, alpha, devX, incx, devY, incy);

// Retrieve resulting vector
cublasGetVector(n, sizeof(*devY), devY, incy, y, incy);

引用the documentation(强调我的):

  

此函数将向量x乘以标量α,将其加到向量y ,用结果覆盖最新向量。

Y既是输入又是输出,但您永远不会设置该值,因此您可以获得未初始化内存中的任何垃圾。在致电cublasSetVector之前,请致电devY以设置cublasDaxpy的初始值。

答案 1 :(得分:0)

所以写的代码完全是完美的。我遇到的唯一问题是我没有正确编译它。根据{{​​3}},每次你改变你的cuda程序(precisley .cu文件)时,你必须重新整个项目,所以Prallel Nsight将编译它。否则它会坚持到最后一次编辑。

这是一个非常微小的观点,但可能会节省很多人,整整一天的调试和无处可去。