23 #define CL_HPP_ENABLE_EXCEPTIONS
24 #define CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY
25 #define CL_HPP_MINIMUM_OPENCL_VERSION 120
26 #define CL_HPP_TARGET_OPENCL_VERSION 120
29 #define CL_HPP_ENABLE_EXCEPTIONS
30 #define CL_HPP_MINIMUM_OPENCL_VERSION 210
31 #define CL_HPP_TARGET_OPENCL_VERSION 210
37 #include "cuda_runtime_api.h"
52 void GpuHelper::FindGpuDevicesCuda() {
57 cudaGetDeviceCount(&n_devices);
60 "No CUDA-compatible GPU found on this machine!");
64 Log::Info(
"",
"Found ", n_devices,
" CUDA-compatible GPU device(s): ");
66 for (
int i = 0; i < n_devices; i++) {
69 cudaGetDeviceProperties(&prop, i);
73 cudaSetDevice(param->preferred_gpu);
75 cudaGetDeviceProperties(&prop, param->preferred_gpu);
76 Log::Info(
"",
"Selected GPU [", param->preferred_gpu,
"]: ", prop.name);
82 Simulation::GetActive()->GetOpenCLState()->ClAssert(err, __FILE__, __LINE__, \
85 void GpuHelper::CompileOpenCLKernels() {
87 auto* param = sim->GetParam();
88 auto* ocl_state = sim->GetOpenCLState();
90 std::vector<cl::Program>* all_programs = ocl_state->GetOpenCLProgramList();
91 cl::Context* context = ocl_state->GetOpenCLContext();
92 std::vector<cl::Device>* devices = ocl_state->GetOpenCLDeviceList();
97 std::string bdmsys = std::getenv(
"BDMSYS");
98 std::ifstream cl_file(
99 bdmsys +
"/include/core/gpu/mechanical_forces_op_opencl_kernel.cl");
100 if (cl_file.fail()) {
101 Log::Error(
"CompileOpenCLKernels",
"Kernel file does not exists!");
103 std::stringstream buffer;
104 buffer << cl_file.rdbuf();
106 cl::Program mechanical_forces_op_program(*context, buffer.str());
108 all_programs->push_back(mechanical_forces_op_program);
110 Log::Info(
"",
"Compiling OpenCL kernels...");
113 if (!ocl_state->HasSupportForDouble() &&
119 "Your GPU does not support double-precision floating point "
120 "operators. In order to use your GPU, consider compiling "
121 "BioDynaMo with -Dreal_t=float");
127 if (param->opencl_debug) {
128 Log::Info(
"",
"Building OpenCL kernels with debugging symbols");
129 options =
Concat(options,
" -g -O0");
131 Log::Info(
"",
"Building OpenCL kernels without debugging symbols");
134 for (
auto& prog : *all_programs) {
136 prog.build(*devices, options.c_str());
137 }
catch (
const cl::Error&) {
138 Log::Error(
"CompileOpenCLKernels",
"OpenCL compilation error: ",
139 prog.getBuildInfo<CL_PROGRAM_BUILD_LOG>((*devices)[0]));
144 void GpuHelper::FindGpuDevicesOpenCL() {
149 auto* param = sim->GetParam();
150 auto* ocl_state = sim->GetOpenCLState();
152 cl::Context* context = ocl_state->GetOpenCLContext();
153 cl::CommandQueue* queue = ocl_state->GetOpenCLCommandQueue();
154 std::vector<cl::Device>* devices = ocl_state->GetOpenCLDeviceList();
157 std::vector<cl::Platform> platform;
160 cl::Platform::get(&platform);
162 if (platform.empty()) {
163 Log::Error(
"FindGpuDevicesOpenCL",
"No OpenCL platforms found");
168 for (
auto p = platform.begin(); p != platform.end(); p++) {
169 std::vector<cl::Device> pldev;
173 p->getDevices(CL_DEVICE_TYPE_GPU, &pldev);
175 for (
auto d = pldev.begin(); d != pldev.end(); d++) {
176 if (!d->getInfo<CL_DEVICE_AVAILABLE>())
179 if (d->getInfo<CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE>()) {
180 ocl_state->EnableSupportForDouble();
182 ocl_state->DisableSupportForDouble();
185 devices->push_back(*d);
189 "Found bad OpenCL platform! Continuing to next one");
195 if (devices->empty()) {
197 "No OpenCL compatible GPU's found on this machine!");
201 *context = cl::Context(*devices);
204 " OpenCL-compatible GPU device(s): ");
206 for (
size_t i = 0; i < devices->size(); i++) {
207 Log::Info(
"",
" [", i,
"] ", (*devices)[i].getInfo<CL_DEVICE_NAME>());
210 int selected_gpu = param->preferred_gpu;
212 if (selected_gpu < 0) {
213 auto itr = std::find(ocl_state->GetFp64Support()->begin(),
214 ocl_state->GetFp64Support()->end(),
true);
215 if (itr == ocl_state->GetFp64Support()->end()) {
217 "No OpenCL compatible GPU's with double precision support "
218 "found on this machine!");
221 selected_gpu = std::distance(ocl_state->GetFp64Support()->begin(), itr);
224 Log::Info(
"",
"Selected GPU [", selected_gpu,
225 "]: ", (*devices)[selected_gpu].getInfo<CL_DEVICE_NAME>());
227 ocl_state->SelectGpu(selected_gpu);
231 *queue = cl::CommandQueue(*context, (*devices)[selected_gpu],
232 CL_QUEUE_PROFILING_ENABLE, &queue_err);
236 CompileOpenCLKernels();
237 }
catch (
const cl::Error& err) {
238 Log::Error(
"FindGpuDevicesOpenCL",
"OpenCL error: ", err.what(),
"(",
242 #endif // defined(USE_OPENCL)
245 #if (defined(USE_CUDA) || defined(USE_OPENCL))
247 if (param->compute_target ==
"opencl") {
249 GpuHelper::FindGpuDevicesOpenCL();
252 "You tried to use the GPU (OpenCL) version of BioDynaMo, but no "
253 "OpenCL installation was detected on this machine. Switching to "
254 "the CPU version...");
258 GpuHelper::FindGpuDevicesCuda();
261 "You tried to use the GPU (CUDA) version of BioDynaMo, but no "
262 "CUDA installation was detected on this machine. Switching to "
263 "the CPU version...");
266 #endif // defined(USE_CUDA) || defined(USE_OPENCL)