Blame view

src/cudamatrix/cu-sparse-matrix.h 8.57 KB
8dcb6dfcb   Yannick Estève   first commit
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
  // cudamatrix/cu-sparse-matrix.h
  
  // Copyright      2015  Johns Hopkins University (author: Daniel Povey)
  //                2015  Guoguo Chen
  //                2017  Shiyin Kang
  
  // See ../../COPYING for clarification regarding multiple authors
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //  http://www.apache.org/licenses/LICENSE-2.0
  //
  // THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  // KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
  // WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
  // MERCHANTABLITY OR NON-INFRINGEMENT.
  // See the Apache 2 License for the specific language governing permissions and
  // limitations under the License.
  
  
  
  #ifndef KALDI_CUDAMATRIX_CU_SPARSE_MATRIX_H_
  #define KALDI_CUDAMATRIX_CU_SPARSE_MATRIX_H_
  
  #include <sstream>
  #include <vector>
  
  #include "cudamatrix/cu-matrixdim.h"
  #include "cudamatrix/cu-common.h"
  #include "cudamatrix/cu-value.h"
  #include "matrix/matrix-common.h"
  #include "matrix/kaldi-matrix.h"
  #include "matrix/sparse-matrix.h"
  #include "cudamatrix/cu-array.h"
  #include "cudamatrix/cu-math.h"
  #include "cudamatrix/cu-rand.h"
  
  namespace kaldi {
  
  template <typename Real>
  Real TraceMatSmat(const CuMatrixBase<Real> &A,
                    const CuSparseMatrix<Real> &B,
                    MatrixTransposeType trans = kNoTrans);
  
  template<class Real>
  class CuSparseMatrix {
  public:
    friend class CuMatrixBase<float> ;
    friend class CuMatrixBase<double> ;
    friend class CuMatrixBase<Real> ;
    friend class CuVectorBase<float> ;
    friend class CuVectorBase<double> ;
    friend class CuVectorBase<Real> ;
  
    friend Real TraceMatSmat<Real>(const CuMatrixBase<Real> &A,
                                   const CuSparseMatrix<Real> &B,
                                   MatrixTransposeType trans);
  
    MatrixIndexT NumRows() const;
  
    MatrixIndexT NumCols() const;
  
    MatrixIndexT NumElements() const;
  
    template<typename OtherReal>
    void CopyToMat(CuMatrixBase<OtherReal> *dest, MatrixTransposeType trans =
                       kNoTrans) const;
  
    Real Sum() const;
  
    Real FrobeniusNorm() const;
  
    /// Copy from CPU-based matrix.
    CuSparseMatrix<Real> &operator =(const SparseMatrix<Real> &smat);
  
    /// Copy from possibly-GPU-based matrix.
    CuSparseMatrix<Real> &operator =(const CuSparseMatrix<Real> &smat);
  
    /// Copy from CPU-based matrix.  We will add the transpose option later when it
    /// is necessary.  Resizes *this as needed.
    template<typename OtherReal>
    void CopyFromSmat(const SparseMatrix<OtherReal> &smat);
  
    /// Copy from GPU-based matrix, supporting transposition.  Resizes *this
    /// as needed.
    void CopyFromSmat(const CuSparseMatrix<Real> &smat,
                      MatrixTransposeType trans = kNoTrans);
  
    /// Select a subset of the rows of a CuSparseMatrix.
    /// Sets *this to only the rows of 'smat_other' that are listed
    /// in 'row_indexes'.
    /// 'row_indexes' must satisfy 0 <= row_indexes[i] < smat_other.NumRows().
    void SelectRows(const CuArray<int32> &row_indexes,
                    const CuSparseMatrix<Real> &smat_other);
  
    /// Copy to CPU-based matrix. We will add the transpose option later when it
    /// is necessary.
    template<typename OtherReal>
    void CopyToSmat(SparseMatrix<OtherReal> *smat) const;
  
    /// Copy elements to CuVector. It is the caller's responsibility to resize
    /// <*vec>.
    void CopyElementsToVec(CuVectorBase<Real> *vec) const;
  
    /// Swap with CPU-based matrix.
    void Swap(SparseMatrix<Real> *smat);
  
    /// Swap with possibly-CPU-based matrix.
    void Swap(CuSparseMatrix<Real> *smat);
  
    /// Sets up to a pseudo-randomly initialized matrix, with each element zero
    /// with probability zero_prob and else normally distributed- mostly for
    /// purposes of testing.
    void SetRandn(BaseFloat zero_prob);
  
    void Write(std::ostream &os, bool binary) const;
  
    void Read(std::istream &is, bool binary);
  
    /// Default constructor
    CuSparseMatrix() :
        num_rows_(0), num_cols_(0), nnz_(0), csr_row_ptr_col_idx_(NULL), csr_val_(
            NULL) {
    }
  
    /// Constructor from CPU-based sparse matrix.
    explicit CuSparseMatrix(const SparseMatrix<Real> &smat) :
        num_rows_(0), num_cols_(0), nnz_(0), csr_row_ptr_col_idx_(NULL), csr_val_(
        NULL) {
      this->CopyFromSmat(smat);
    }
  
    /// Constructor from GPU-based sparse matrix (supports transposition).
    CuSparseMatrix(const CuSparseMatrix<Real> &smat, MatrixTransposeType trans =
                       kNoTrans) :
        num_rows_(0), num_cols_(0), nnz_(0), csr_row_ptr_col_idx_(NULL), csr_val_(
        NULL) {
      this->CopyFromSmat(smat, trans);
    }
  
    /// Constructor from an array of indexes.
    /// If trans == kNoTrans, construct a sparse matrix
    /// with num-rows == indexes.Dim() and num-cols = 'dim'.
    /// 'indexes' is expected to contain elements in the
    /// range [0, dim - 1].  Each row 'i' of *this after
    /// calling the constructor will contain  a single
    /// element at column-index indexes[i] with value 1.0.
    ///
    /// If trans == kTrans, the result will be the transpose
    /// of the sparse matrix described above.
    CuSparseMatrix(const CuArray<int32> &indexes, int32 dim,
                   MatrixTransposeType trans = kNoTrans);
  
    /// Constructor from an array of indexes and an array of
    /// weights; requires indexes.Dim() == weights.Dim().
    /// If trans == kNoTrans, construct a sparse matrix
    /// with num-rows == indexes.Dim() and num-cols = 'dim'.
    /// 'indexes' is expected to contain elements in the
    /// range [0, dim - 1].  Each row 'i' of *this after
    /// calling the constructor will contain a single
    /// element at column-index indexes[i] with value weights[i].
    /// If trans == kTrans, the result will be the transpose
    /// of the sparse matrix described above.
    CuSparseMatrix(const CuArray<int32> &indexes,
                   const CuVectorBase<Real> &weights, int32 dim,
                   MatrixTransposeType trans = kNoTrans);
  
    ~CuSparseMatrix() {
      Destroy();
    }
  
  protected:
    // The following two functions should only be called if we did not compile
    // with CUDA or could not get a CUDA card; in that case the contents are
    // interpreted the same as a regular sparse matrix.
    inline const SparseMatrix<Real> &Smat() const {
      return *(reinterpret_cast<const SparseMatrix<Real>*>(this));
    }
    inline SparseMatrix<Real> &Smat() {
      return *(reinterpret_cast<SparseMatrix<Real>*>(this));
    }
  
    /// Users of this class won't normally have to use Resize.
    /// 'nnz' should be determined beforehand when calling this API.
    void Resize(const MatrixIndexT num_rows, const MatrixIndexT num_cols,
                const MatrixIndexT nnz, MatrixResizeType resize_type = kSetZero);
  
    /// Returns pointer to the data array of length nnz_ that holds all nonzero
    /// values in zero-based CSR format
    const Real* CsrVal() const {
      return csr_val_;
    }
    Real* CsrVal() {
      return csr_val_;
    }
  
    /// Returns pointer to the integer array of length NumRows()+1 that holds
    /// indices of the first nonzero element in the i-th row, while the last entry
    /// contains nnz_, as zero-based CSR format is used.
    const int* CsrRowPtr() const {
      return csr_row_ptr_col_idx_;
    }
    int* CsrRowPtr() {
      return csr_row_ptr_col_idx_;
    }
  
    /// Returns pointer to the integer array of length nnz_ that contains
    /// the column indices of the corresponding elements in array CsrVal()
    const int* CsrColIdx() const {
      return csr_row_ptr_col_idx_ + num_rows_ + 1;
    }
    int* CsrColIdx() {
      return csr_row_ptr_col_idx_ + num_rows_ + 1;
    }
  
  private:
    void Destroy();
  
  private:
    // This member is only used if we did not compile for the GPU, or if the GPU
    // is not enabled.  It needs to be first because we reinterpret_cast this
    std::vector<SparseVector<Real> > cpu_rows_;
  
    // This is where the data lives if we are using a GPU.
    // The sparse matrix is stored in CSR format, as documented here.
    // http://docs.nvidia.com/cuda/cusparse/index.html#compressed-sparse-row-format-csr
    // The 3 arrays are stored in 2 allocated blocks of memory.
    // Row ptr and col idx are both int arrays, thus stored in one block pointed
    // 'by csr_row_ptr_col_idx_'
    // Val are Real array, pointed by `csr_val_`
  
    // matrix size num_rows_ x num_cols_
    MatrixIndexT num_rows_;
    MatrixIndexT num_cols_;
  
    // number of non-zeros
    MatrixIndexT nnz_;
  
    // csr row ptrs and col indices in a single int array
    // of the length (num_rows_ + 1 + nnz_)
    int* csr_row_ptr_col_idx_;
  
    // csr value array of the length nnz_
    Real* csr_val_;
  };
  
  
  }  // namespace
  
  #endif  // KALDI_CUDAMATRIX_CU_SPARSE_MATRIX_H_