Coverage Control Library
Loading...
Searching...
No Matches
cuda_utils.cu
Go to the documentation of this file.
1/*
2 * This file is part of the CoverageControl library
3 *
4 * Author: Saurav Agarwal
5 * Contact: sauravag@seas.upenn.edu, agr.saurav1@gmail.com
6 * Repository: https://github.com/KumarRobotics/CoverageControl
7 *
8 * Copyright (c) 2024, Saurav Agarwal
9 *
10 * The CoverageControl library is free software: you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 3 of the License, or (at your
13 * option) any later version.
14 *
15 * The CoverageControl library is distributed in the hope that it will be
16 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
18 * Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * CoverageControl library. If not, see <https://www.gnu.org/licenses/>.
22 */
23
30#include <cuda_runtime.h>
31
32#include <iostream>
33
35#include "CoverageControl/extern/cuda_helpers/helper_cuda.h"
36#include "CoverageControl/extern/cuda_helpers/helper_string.h"
37
38namespace CoverageControl {
39
40bool CheckCudaErrors(cudaError_t result) {
41 if (result != cudaSuccess) {
42 std::cerr << "CUDA error: [" << static_cast<unsigned int>(result) << "] "
43 << cudaGetErrorString(result) << std::endl;
44 return false;
45 }
46 return true;
47}
48
49bool CudaUtils::GetDeviceCount(int &device_count) {
50 CheckCudaErrors(cudaGetDeviceCount(&device_count));
51 if (device_count == 0) {
52 /* std::cerr << "No CUDA devices found" << std::endl; */
53 return false;
54 }
55 return true;
56}
57
58int CudaUtils::GPUDeviceInit(int dev_id) {
59 int device_count;
60 bool device_count_success = GetDeviceCount(device_count);
61 if (!device_count_success) {
62 return -1;
63 }
64
65 if (dev_id < 0) {
66 dev_id = 0;
67 }
68
69 if (dev_id > device_count - 1) {
70 std::cerr << "Invalid GPU device ID" << std::endl;
71 std::cerr << "Device ID: " << dev_id << " Device Count: " << device_count
72 << std::endl;
73 return -1;
74 }
75
76 int compute_mode = -1, major = 0, minor = 0;
78 cudaDeviceGetAttribute(&compute_mode, cudaDevAttrComputeMode, dev_id));
79 CheckCudaErrors(cudaDeviceGetAttribute(
80 &major, cudaDevAttrComputeCapabilityMajor, dev_id));
81 CheckCudaErrors(cudaDeviceGetAttribute(
82 &minor, cudaDevAttrComputeCapabilityMinor, dev_id));
83 if (compute_mode == cudaComputeModeProhibited) {
84 std::cerr << "Error: device is running in <Compute Mode Prohibited>, no "
85 "threads can use cudaSetDevice()."
86 << std::endl;
87 return -1;
88 }
89
90 if (major < 1) {
91 std::cerr << "GPUDeviceInit(): GPU device does not support CUDA."
92 << std::endl;
93 return -1;
94 }
95
96 CheckCudaErrors(cudaSetDevice(dev_id));
97 /* std::cout << "GPU Device " << dev_id << " has been set" << std::endl; */
98 /* std::cout << "CUDA Device [" << dev_id << "]: \"" */
99 /* << _ConvertSMVer2ArchName(major, minor) << "\"" << std::endl; */
100 is_cuda_initialized_ = true;
101 device_id_ = dev_id;
102 return dev_id;
103}
104
105int CudaUtils::FindDevice() { return GPUGetMaxGflopsDeviceId(); }
106
107int CudaUtils::FindIntegratedGPU() {
108 int current_device = 0;
109 int device_count = 0;
110 int devices_prohibited = 0;
111
112 CheckCudaErrors(cudaGetDeviceCount(&device_count));
113
114 if (device_count == 0) {
115 /* std::cerr << "No CUDA devices found" << std::endl; */
116 return -1;
117 }
118
119 // Find the integrated GPU which is compute capable
120 while (current_device < device_count) {
121 int compute_mode = -1, integrated = -1;
122 CheckCudaErrors(cudaDeviceGetAttribute(
123 &compute_mode, cudaDevAttrComputeMode, current_device));
124 CheckCudaErrors(cudaDeviceGetAttribute(&integrated, cudaDevAttrIntegrated,
125 current_device));
126 // If GPU is integrated and is not running on Compute Mode prohibited,
127 // then cuda can map to GLES resource
128 if (integrated && (compute_mode != cudaComputeModeProhibited)) {
129 CheckCudaErrors(cudaSetDevice(current_device));
130
131 int major = 0, minor = 0;
132 CheckCudaErrors(cudaDeviceGetAttribute(
133 &major, cudaDevAttrComputeCapabilityMajor, current_device));
134 CheckCudaErrors(cudaDeviceGetAttribute(
135 &minor, cudaDevAttrComputeCapabilityMinor, current_device));
136 /* std::cout << "GPU Device " << current_device << " has been set" */
137 /* << std::endl; */
138 /* std::cout << "CUDA Device [" << current_device << "]: \"" */
139 /* << _ConvertSMVer2ArchName(major, minor) << "\"" << std::endl; */
140 return current_device;
141 } else {
142 devices_prohibited++;
143 }
144
145 current_device++;
146 }
147
148 if (devices_prohibited == device_count) {
149 std::cerr << "CUDA error: No Integrated GPU found that supports CUDA."
150 << std::endl;
151 return -1;
152 }
153
154 return -1;
155}
156
163int CudaUtils::GPUGetMaxGflopsDeviceId(std::vector<int> device_list) {
164 int sm_per_multiproc = 0;
165 int max_perf_device = 0;
166 int device_count = 0;
167 int devices_prohibited = 0;
168
169 uint64_t max_compute_perf = 0;
170
171 if (GetDeviceCount(device_count) == false) {
172 return -1;
173 }
174
175 if (device_count == 0) {
176 /* std::cerr << "No CUDA devices found" << std::endl; */
177 return -1;
178 }
179
180 if (device_list.size() == 0) {
181 for (int i = 0; i < device_count; i++) {
182 device_list.push_back(i);
183 }
184 }
185
186 while (device_list.size() > 0) {
187 int current_device = device_list.back();
188 device_list.pop_back();
189 int compute_mode = -1, major = 0, minor = 0;
190 CheckCudaErrors(cudaDeviceGetAttribute(
191 &compute_mode, cudaDevAttrComputeMode, current_device));
192 CheckCudaErrors(cudaDeviceGetAttribute(
193 &major, cudaDevAttrComputeCapabilityMajor, current_device));
194 CheckCudaErrors(cudaDeviceGetAttribute(
195 &minor, cudaDevAttrComputeCapabilityMinor, current_device));
196
197 // If this GPU is not running on Compute Mode prohibited,
198 // then we can add it to the list
199 if (compute_mode != cudaComputeModeProhibited) {
200 if (major == 9999 && minor == 9999) {
201 sm_per_multiproc = 1;
202 } else {
203 sm_per_multiproc = _ConvertSMVer2Cores(major, minor);
204 }
205 int multiProcessorCount = 0, clockRate = 0;
206 CheckCudaErrors(cudaDeviceGetAttribute(&multiProcessorCount,
207 cudaDevAttrMultiProcessorCount,
208 current_device));
209 cudaError_t result = cudaDeviceGetAttribute(
210 &clockRate, cudaDevAttrClockRate, current_device);
211 if (result != cudaSuccess) {
212 // If cudaDevAttrClockRate attribute is not supported we
213 // set clockRate as 1, to consider GPU with most SMs and CUDA Cores.
214 if (result == cudaErrorInvalidValue) {
215 clockRate = 1;
216 } else {
217 fprintf(stderr, "CUDA error at %s:%d code=%d(%s) \n", __FILE__,
218 __LINE__, static_cast<unsigned int>(result),
219 _cudaGetErrorEnum(result));
220 return -1;
221 }
222 }
223 uint64_t compute_perf =
224 (uint64_t)multiProcessorCount * sm_per_multiproc * clockRate;
225
226 if (compute_perf > max_compute_perf) {
227 max_compute_perf = compute_perf;
228 max_perf_device = current_device;
229 }
230 } else {
231 devices_prohibited++;
232 }
233 }
234
235 if (devices_prohibited == device_count) {
236 std::cerr << "GPUGetMaxGflopsDeviceId() CUDA error:"
237 << " all devices have compute mode prohibited." << std::endl;
238 return -1;
239 }
240
241 return max_perf_device;
242}
243
244} /* namespace CoverageControl */
Utility functions for CUDA.
Namespace for the CoverageControl library.
bool CheckCudaErrors(cudaError_t result)
Definition cuda_utils.cu:40