ATLAS Offline Software
Loading...
Searching...
No Matches
KernelRunnerSvc.cxx
Go to the documentation of this file.
1//
2// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
3//
4
5// Local include(s).
6#include "KernelRunnerSvc.h"
7
8// Project include(s).
9#include "AthCUDACore/Info.h"
10
11// System include(s).
12#include <cassert>
13#include <sstream>
14#include <thread>
15
16namespace AthCUDA {
17
19
20 // Reset the internal counter(s).
22 m_totalTasks = 0;
23 m_gpuTasks = 0;
24
25 // If no devices are available or no kernels are allowed to run on the
26 // GPU, then don't even set up the implementation object.
27 if( ( Info::instance().nDevices() == 0 ) ||
28 ( m_nKernels.value() == 0 ) ) {
29 ATH_MSG_INFO( "Will run everything on the CPU." );
30 return StatusCode::SUCCESS;
31 }
32
33 // Access the stream pool service.
34 ATH_CHECK( m_streamPoolSvc.retrieve() );
35
36 // Create the implementation object.
37 m_impl = std::make_unique< KernelRunnerSvcImpl >( *m_streamPoolSvc,
38 *this );
39
40 // Tell the user what happened.
41 std::ostringstream str;
43 ATH_MSG_INFO( "Started service for running " << m_nKernels.value()
44 << " GPU kernel(s) in parallel on device(s):\n"
45 << str.str() );
46
47 // Return gracefully.
48 return StatusCode::SUCCESS;
49 }
50
52
53 // Destroy the implementation object.
54 m_impl.reset();
55
56 // Tell the user what happened.
57 ATH_MSG_INFO( " o All task(s) executed: " << m_totalTasks.load() );
58 const double percentage =
59 ( m_totalTasks != 0 ?
60 ( static_cast< double >( m_gpuTasks.load() ) /
61 static_cast< double >( m_totalTasks.load() ) * 100.0 ) : 0.0 );
62 ATH_MSG_INFO( " o GPU task(s) executed: " << m_gpuTasks.load() << " ("
63 << percentage << "%)" );
64
65 // Finalise the base class.
66 ATH_CHECK( Service::finalize() );
67
68 // Return gracefully.
69 return StatusCode::SUCCESS;
70 }
71
72 StatusCode KernelRunnerSvc::execute( std::unique_ptr< IKernelTask > task ) {
73
74 // Make sure that we received a valid task.
75 if( task.get() == nullptr ) {
76 ATH_MSG_ERROR( "Invalid task object received" );
77 return StatusCode::FAILURE;
78 }
79
80 // One way or another, we will execute this task.
82
83 // Check if a GPU is available, and no other thread is launching a GPU
84 // calculation right now.
85 if( ( ! m_impl ) || m_streamPoolSvc->isEmpty() ||
86 ( ( m_nKernels.value() > 0 ) &&
87 ( m_kernelsInFlight.load() >= m_nKernels.value() ) ) ) {
88
89 // If so, let's just execute the task in the current thread.
90 ATH_MSG_VERBOSE( "Executing a task on the CPU" );
91 StreamHolder dummy;
92 if( task->finished( task->execute( dummy ),
94 ATH_MSG_ERROR( "Failed to execute task in the caller thread!" );
95 return StatusCode::FAILURE;
96 }
97
98 // Return gracefully.
99 return StatusCode::SUCCESS;
100 }
101
102 // If we got here, we need to schedule the task for execution on the/a
103 // GPU.
104
105 // Give the task to the implementation object to launch it.
106 ATH_MSG_VERBOSE( "Executing an offloaded task" );
108 ++m_gpuTasks;
109 m_impl->execute( std::move( task ) );
110
111 // Return gracefully.
112 return StatusCode::SUCCESS;
113 }
114
116
117 // Update the internal counter.
119 return;
120 }
121
122} // namespace AthCUDA
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
@ Synchronous
The kernel was executed synchronously on the CPU.
Definition IKernelTask.h:31
static const Info & instance()
Singleton accessor function.
std::atomic_uint m_gpuTasks
The number of tasks sent to the GPU during the job.
std::atomic_uint m_totalTasks
The number of tasks executed during the job in total.
virtual StatusCode initialize() override
Initialise the service.
virtual StatusCode finalize() override
Finalise the service.
Gaudi::Property< int > m_nKernels
The number of streams to use.
ServiceHandle< IStreamPoolSvc > m_streamPoolSvc
Service managing CUDA the streams.
std::unique_ptr< KernelRunnerSvcImpl > m_impl
Implementation helper object.
virtual StatusCode execute(std::unique_ptr< IKernelTask > task) override
Execute a user specified kernel task.
std::atomic_int m_kernelsInFlight
The current number of kernels being executed.
Helper class for handling CUDA streams.
Definition Info.h:14