title: Singular values calculation only with CUDA
body: <p>I'm trying to use the new <code>cusolverDnSgesvd</code> routine of CUDA 7.0 for the calculation of the singular values. The full code is reported below:</p>
  
  <pre><code>#include "cuda_runtime.h"
  #include "device_launch_parameters.h"
  
  #include &lt;stdio.h&gt;
  
  #include&lt;iostream&gt;
  #include&lt;stdlib.h&gt;
  #include&lt;stdio.h&gt;
  #include &lt;cusolverDn.h&gt;
  #include &lt;cuda_runtime_api.h&gt;
  
  /***********************/
  /* CUDA ERROR CHECKING */
  /***********************/
  void gpuAssert(cudaError_t code, char *file, int line, bool abort=true)
  {
     if (code != cudaSuccess)
     {
        fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
        if (abort) { exit(code); }
     }
  }
  void gpuErrchk(cudaError_t ans) { gpuAssert((ans), __FILE__, __LINE__); }
  
  /********/
  /* MAIN */
  /********/
  int main(){
  
      int M = 10;
      int N = 10;
  
      // --- Setting the host matrix
      float *h_A = (float *)malloc(M * N * sizeof(float));
      for(unsigned int i = 0; i &lt; M; i++){
          for(unsigned int j = 0; j &lt; N; j++){
              h_A[j*M + i] = (i + j) * (i + j);
          }
      }
  
      // --- Setting the device matrix and moving the host matrix to the device
      float *d_A;         gpuErrchk(cudaMalloc(&amp;d_A,      M * N * sizeof(float)));
      gpuErrchk(cudaMemcpy(d_A, h_A, M * N * sizeof(float), cudaMemcpyHostToDevice));
  
      // --- host side SVD results space
      float *h_U = (float *)malloc(M * M * sizeof(float));
      float *h_V = (float *)malloc(N * N * sizeof(float));
      float *h_S = (float *)malloc(N *     sizeof(float));
  
      // --- device side SVD workspace and matrices
      int work_size = 0;
  
      int *devInfo;       gpuErrchk(cudaMalloc(&amp;devInfo,          sizeof(int)));
      float *d_U;         gpuErrchk(cudaMalloc(&amp;d_U,      M * M * sizeof(float)));
      float *d_V;         gpuErrchk(cudaMalloc(&amp;d_V,      N * N * sizeof(float)));
      float *d_S;         gpuErrchk(cudaMalloc(&amp;d_S,      N *     sizeof(float)));
  
      cusolverStatus_t stat;
  
      // --- CUDA solver initialization
      cusolverDnHandle_t solver_handle;
      cusolverDnCreate(&amp;solver_handle);
  
      stat = cusolverDnSgesvd_bufferSize(solver_handle, M, N, &amp;work_size);
      if(stat != CUSOLVER_STATUS_SUCCESS ) std::cout &lt;&lt; "Initialization of cuSolver failed. \N";
  
      float *work;    gpuErrchk(cudaMalloc(&amp;work, work_size * sizeof(float)));
      //float *rwork; gpuErrchk(cudaMalloc(&amp;rwork, work_size * sizeof(float)));
  
      // --- CUDA SVD execution
      //stat = cusolverDnSgesvd(solver_handle, 'A', 'A', M, N, d_A, M, d_S, d_U, M, d_V, N, work, work_size, NULL, devInfo);
      stat = cusolverDnSgesvd(solver_handle, 'N', 'N', M, N, d_A, M, d_S, d_U, M, d_V, N, work, work_size, NULL, devInfo);
      cudaDeviceSynchronize();
  
      int devInfo_h = 0;
      gpuErrchk(cudaMemcpy(&amp;devInfo_h, devInfo, sizeof(int), cudaMemcpyDeviceToHost));
      std::cout &lt;&lt; "devInfo = " &lt;&lt; devInfo_h &lt;&lt; "\n";
  
      switch(stat){
          case CUSOLVER_STATUS_SUCCESS:           std::cout &lt;&lt; "SVD computation success\n";                       break;
          case CUSOLVER_STATUS_NOT_INITIALIZED:   std::cout &lt;&lt; "Library cuSolver not initialized correctly\n";    break;
          case CUSOLVER_STATUS_INVALID_VALUE:     std::cout &lt;&lt; "Invalid parameters passed\n";                     break;
          case CUSOLVER_STATUS_INTERNAL_ERROR:    std::cout &lt;&lt; "Internal operation failed\n";                     break;
      }
  
      if (devInfo_h == 0 &amp;&amp; stat == CUSOLVER_STATUS_SUCCESS) std::cout    &lt;&lt; "SVD successful\n\n";
  
      // --- Moving the results from device to host
      gpuErrchk(cudaMemcpy(h_S, d_S, N * sizeof(float), cudaMemcpyDeviceToHost));
  
      for(int i = 0; i &lt; N; i++) std::cout &lt;&lt; "d_S["&lt;&lt;i&lt;&lt;"] = " &lt;&lt; h_S[i] &lt;&lt; std::endl;
  
      cusolverDnDestroy(solver_handle);
  
      return 0;
  
  }
  </code></pre>
  
  <p>If I ask for the computation of the full SVD (commented line with <code>jobu = 'A'</code> and <code>jobvt = 'A'</code>) everything works fine. If I ask for the computation of the singular values only (line with <code>jobu = 'N'</code> and <code>jobvt = 'N'</code>), <code>cusolverDnSgesvd</code> returns  </p>
  
  <pre><code>CUSOLVER_STATUS_INVALID_VALUE
  </code></pre>
  
  <p>Please note that, in this case <code>devInfo = 0</code>, so I cannot spot the invalid parameter.</p>
  
  <p>Please also note that the documentation PDF lacks information about the <code>rwork</code> parameter so that I have dealt with it as a dummy parameter.</p>