-1

I am looking for a way to convert

Eigen::SparseMatrix< float> <-> cusp::hyb_matrix< int, float, cusp::host_memory>

back and forth.

The Eigen matrix is a result of a previous computation and I need a cusp::hyb_matrix to use the GPU for conjugate gradient computation later.

Thanks.

The Hiary
  • 109
  • 1
  • 13
Vtik
  • 3,073
  • 2
  • 23
  • 38
  • That is nice. Did you have an actual question to ask? – talonmies Nov 20 '17 at 15:45
  • "I am looking for a way" pretty sure means how ... – Vtik Nov 20 '17 at 15:54
  • 1
    Well I am looking for a way to predict the winning lottery numbers. It doesn't mean either of us has an actual valid [SO] question, What *specifically* do you not understand in your attempt to write code which performs this format conversion? – talonmies Nov 20 '17 at 18:26

1 Answers1

0

Well, I have found a workaround that does what needed but a more direct way is still missing.

Based on this example, i just needed to extract the rows/cols/coeffs vectors of values from the Eigen::SparseMatrix to construct a cusp::hyb_matrix. This can be done as follows :

void SparseMatrix2Coo(Eigen::SparseMatrix<float> Matrix, std::vector<int>& rows, std::vector<int>& cols, std::vector<float>& coeffs)
{
rows.clear();
cols.clear();
coeffs.clear();
for (int k=0; k < Matrix.outerSize(); ++k)
{
    for (Eigen::SparseMatrix<float>::InnerIterator it(Matrix,k); it; ++it)
    {
        rows.push_back(it.row());
        cols.push_back(it.col());
        coeffs.push_back(Matrix.coeff(it.row(), it.col()));
    }
}
assert(cols.size() == coeffs.size());
assert(rows.size() == cols.size());
}

Now, once we have rows/cols/coeffs, we just need to use those in the example above as inputs :

void computeConjugateGradientGPU(std::vector<int>& rows, std::vector<int>& cols, std::vector<float>& coeffs, std::vector<float>& b, Eigen::VectorXf& x)
{
int arrays_size = rows.size();
/// allocate device memory for CSR format
int   * device_I;
cudaMalloc(&device_I, arrays_size * sizeof(int));
int   * device_J;
cudaMalloc(&device_J, arrays_size * sizeof(int));
float * device_V;
cudaMalloc(&device_V, arrays_size * sizeof(float));

float * device_b;
cudaMalloc(&device_b, b.size() * sizeof(float));

/// copy raw data from host to device
cudaMemcpy(device_I, &cols[0], arrays_size * sizeof(int),   cudaMemcpyHostToDevice);
cudaMemcpy(device_J, &rows[0], arrays_size * sizeof(int),   cudaMemcpyHostToDevice);
cudaMemcpy(device_V, &coeffs[0], arrays_size * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(device_b, &b[0],  b.size() * sizeof(float), cudaMemcpyHostToDevice);

/// and the rest is the same...
}

The other way around is pretty obvious with the same logic.

Hope this helps someone.

Cheers.

Vtik
  • 3,073
  • 2
  • 23
  • 38