2016-04-26 10 views
1

Я написал оболочку в C++ 11/CLI с Visual Studio для использования CuBLAS CUDA. Я использую CUDA Toolkit 7.0.Неожиданные результаты при вызове cublas в C++/CLI и C#

Вот исходный код моей обертки:

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

EDIT: Я добавил новое предложение Дэвида Яу, а также добавил проверку ошибок для всех операций cuda. но я не записывал все ошибки здесь из-за удобочитаемости. все еще не работает.

ответ

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 (курсив моего):

Эта функция умножает вектор х скалярные а и добавляет его к вектору у перезаписи последнего вектора с результатом.

Y одновременно вход и выход, но вы никогда не устанавливая значение, так что вы получите то, что нездоровой находится в неинициализированной памяти. Добавьте звонок в cublasSetVector, чтобы установить начальное значение devY, прежде чем позвонить cublasDaxpy.

+0

Это был хороший момент, но он все еще не работает. Я даже добавил много ошибок в коде cuda, но он все равно не работает. это похоже на то, что он никогда не достигает кода cuda. Однако я добавляю вашу точку и исключения из основного вопроса. – Afshinzkh

0

Так что код, написанный Up, полностью совершенен. Единственная проблема, с которой я столкнулся, - это не скомпилировать ее должным образом. в соответствии с This Tutorial, каждый раз, когда вы вносите изменения в свою программу cuda (precisley .cu-файл), вы должны ЗАПРЕТИТЬ весь проект, чтобы Prallel Nsight скомпилировал его. иначе он будет придерживаться последней компиляции.

Это очень крошечный момент, но может сэкономить много людей, целый день отладки и получения ниоткуда.

+0

Это верно для любого проекта в Visual Studio. Это не уникально для CUDA или параллельного nsight. После внесения изменений кода вам придется перекомпилировать. Это довольно простой принцип любого компьютерного программирования с использованием скомпилированных кодов. –