1 /*
2 * Copyright 2009-2020 The VOTCA Development Team
3 * (http://www.votca.org)
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License")
6 *
7 * You may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 *Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 */
19
20 // Local VOTCA includes
21 #include "votca/xtp/cudamatrix.h"
22
23 namespace votca {
24 namespace xtp {
checkCuda(cudaError_t result)25 void checkCuda(cudaError_t result) {
26 if (result != cudaSuccess) {
27 throw std::runtime_error(std::string("CUDA Runtime Error: ") +
28 cudaGetErrorString(result));
29 }
30 }
31
checkCublas(cublasStatus_t result)32 void checkCublas(cublasStatus_t result) {
33 if (result != CUBLAS_STATUS_SUCCESS) {
34 throw std::runtime_error(std::string("CUBLAS Runtime Error: ") +
35 cudaGetErrorEnum(result));
36 }
37 }
38
cudaGetErrorEnum(cublasStatus_t error)39 std::string cudaGetErrorEnum(cublasStatus_t error) {
40 switch (error) {
41 case CUBLAS_STATUS_SUCCESS:
42 return "CUBLAS_STATUS_SUCCESS";
43 case CUBLAS_STATUS_NOT_INITIALIZED:
44 return "CUBLAS_STATUS_NOT_INITIALIZED";
45 case CUBLAS_STATUS_ALLOC_FAILED:
46 return "CUBLAS_STATUS_ALLOC_FAILED";
47 case CUBLAS_STATUS_INVALID_VALUE:
48 return "CUBLAS_STATUS_INVALID_VALUE";
49 case CUBLAS_STATUS_ARCH_MISMATCH:
50 return "CUBLAS_STATUS_ARCH_MISMATCH";
51 case CUBLAS_STATUS_MAPPING_ERROR:
52 return "CUBLAS_STATUS_MAPPING_ERROR";
53 case CUBLAS_STATUS_EXECUTION_FAILED:
54 return "CUBLAS_STATUS_EXECUTION_FAILED";
55 case CUBLAS_STATUS_INTERNAL_ERROR:
56 return "CUBLAS_STATUS_INTERNAL_ERROR";
57 case CUBLAS_STATUS_NOT_SUPPORTED:
58 return "CUBLAS_STATUS_NOT_SUPPORTED";
59 case CUBLAS_STATUS_LICENSE_ERROR:
60 return "CUBLAS_STATUS_LICENSE_ERROR";
61 }
62 return "<unknown>";
63 }
64
count_available_gpus()65 Index count_available_gpus() {
66 int count;
67 cudaError_t err = cudaGetDeviceCount(&count);
68 return (err != cudaSuccess) ? 0 : Index(count);
69 }
70
CudaMatrix(Index nrows,Index ncols,const cudaStream_t & stream)71 CudaMatrix::CudaMatrix(Index nrows, Index ncols, const cudaStream_t& stream)
72 : ld_(nrows), cols_(ncols) {
73 data_ = alloc_matrix_in_gpu(size_matrix());
74 stream_ = stream;
75 }
76
operator Eigen::MatrixXd() const77 CudaMatrix::operator Eigen::MatrixXd() const {
78 Eigen::MatrixXd result = Eigen::MatrixXd::Zero(this->rows(), this->cols());
79 checkCuda(cudaMemcpyAsync(result.data(), this->data(), this->size_matrix(),
80 cudaMemcpyDeviceToHost, this->stream_));
81 checkCuda(cudaStreamSynchronize(this->stream_));
82 return result;
83 }
84
setZero()85 void CudaMatrix::setZero() { cudaMemset(data_.get(), 0, size_matrix()); }
86
alloc_matrix_in_gpu(size_t size_arr) const87 CudaMatrix::Unique_ptr_to_GPU_data CudaMatrix::alloc_matrix_in_gpu(
88 size_t size_arr) const {
89 double* dmatrix;
90 throw_if_not_enough_memory_in_gpu(size_arr);
91 checkCuda(cudaMalloc(&dmatrix, size_arr));
92 Unique_ptr_to_GPU_data dev_ptr(dmatrix,
93 [](double* x) { checkCuda(cudaFree(x)); });
94 return dev_ptr;
95 }
96
throw_if_not_enough_memory_in_gpu(size_t requested_memory) const97 void CudaMatrix::throw_if_not_enough_memory_in_gpu(
98 size_t requested_memory) const {
99 size_t free, total;
100 checkCuda(cudaMemGetInfo(&free, &total));
101
102 std::ostringstream oss;
103 oss << "There were requested : " << requested_memory
104 << "bytes Index the device\n";
105 oss << "Device Free memory (bytes): " << free
106 << "\nDevice total Memory (bytes): " << total << "\n";
107
108 // Raise an error if there is not enough total or free memory in the device
109 if (requested_memory > free) {
110 oss << "There is not enough memory in the Device!\n";
111 throw std::runtime_error(oss.str());
112 }
113 }
114
operator <<(std::ostream & out,const CudaMatrix & m)115 std::ostream& operator<<(std::ostream& out, const CudaMatrix& m) {
116 Eigen::MatrixXd temp = m;
117 out << temp;
118 return out;
119 }
120
121 } // namespace xtp
122 } // namespace votca
123