GCC Code Coverage Report


Directory: src/
File: src/talp/talp_gpu.c
Date: 2026-10-14 08:39:21
Exec Total Coverage
Lines: 5 71 7.0%
Functions: 1 6 16.7%
Branches: 1 42 2.4%

Line Branch Exec Source
1 /*********************************************************************************/
2 /* Copyright 2009-2026 Barcelona Supercomputing Center */
3 /* */
4 /* This file is part of the DLB library. */
5 /* */
6 /* DLB is free software: you can redistribute it and/or modify */
7 /* it under the terms of the GNU Lesser General Public License as published by */
8 /* the Free Software Foundation, either version 3 of the License, or */
9 /* (at your option) any later version. */
10 /* */
11 /* DLB is distributed in the hope that it will be useful, */
12 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
13 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
14 /* GNU Lesser General Public License for more details. */
15 /* */
16 /* You should have received a copy of the GNU Lesser General Public License */
17 /* along with DLB. If not, see <https://www.gnu.org/licenses/>. */
18 /*********************************************************************************/
19
20 #include "talp/talp_gpu.h"
21
22 #include "apis/dlb_errors.h"
23 #include "LB_core/spd.h"
24 #include "LB_core/thread_ctx.h"
25 #include "support/debug.h"
26 #include "support/dlb_common.h"
27 #include "support/gpu_mask_utils.h"
28 #include "talp/backend.h"
29 #include "talp/backend_manager.h"
30 #include "talp/regions.h"
31 #include "talp/sample.h"
32 #include "talp/talp.h"
33 #include "talp/talp_output.h"
34 #include "talp/talp_types.h"
35
36 #include <string.h>
37
38
39 static const backend_api_t *gpu_backend_api = NULL;
40 static gpu_device_entry_t *devices = NULL;
41 static size_t num_devices = 0;
42
43 // Called from talp core
44 20 int talp_gpu_init(const subprocess_descriptor_t *spd) {
45
46 20 gpu_backend_api = talp_backend_manager_load_gpu_backend(spd->options.talp_gpu_backend);
47
1/2
✓ Branch 0 taken 20 times.
✗ Branch 1 not taken.
20 if (gpu_backend_api == NULL) {
48 20 debug_warning("GPU backend could not be loaded");
49 20 return DLB_ERR_UNKNOWN;
50 }
51
52 int error;
53
54 /* If GPU component is not explicitly set, probe plugin first */
55 ✗ if (!(spd->options.talp & TALP_COMPONENT_GPU)) {
56 ✗ error = gpu_backend_api->probe();
57 ✗ if (error == DLB_BACKEND_ERROR) {
58 ✗ debug_warning("HWC backend probe failed");
59 ✗ return DLB_ERR_UNKNOWN;
60 }
61 }
62
63 ✗ error = gpu_backend_api->init(&core_api);
64 ✗ if (error == DLB_BACKEND_ERROR) {
65 ✗ debug_warning("GPU backend could not be initialized");
66 ✗ return DLB_ERR_UNKNOWN;
67 }
68
69 ✗ error = gpu_backend_api->start();
70 ✗ if (error == DLB_BACKEND_ERROR) {
71 ✗ debug_warning("GPU backend could not be started");
72 ✗ gpu_backend_api->finalize();
73 ✗ return DLB_ERR_UNKNOWN;
74 }
75
76 ✗ if (gpu_backend_api->capabilities.gpu_amd) {
77 ✗ talp_output_record_gpu_vendor(GPU_VENDOR_AMD);
78 ✗ } else if (gpu_backend_api->capabilities.gpu_nvidia) {
79 ✗ talp_output_record_gpu_vendor(GPU_VENDOR_NVIDIA);
80 }
81
82 ✗ error = gpu_backend_api->gpu.get_devices(NULL, 0, &num_devices);
83 ✗ if (error == DLB_BACKEND_ERROR || num_devices == 0) {
84 ✗ debug_warning("GPU backend could not obtain number of devices");
85 ✗ gpu_backend_api->stop();
86 ✗ gpu_backend_api->finalize();
87 }
88
89 ✗ devices = malloc(sizeof(*devices) * num_devices);
90 ✗ error = gpu_backend_api->gpu.get_devices(devices, num_devices, NULL);
91 ✗ if (error == DLB_BACKEND_ERROR) {
92 ✗ debug_warning("GPU backend could not obtain device unique IDs");
93 ✗ gpu_backend_api->stop();
94 ✗ gpu_backend_api->finalize();
95 }
96
97 ✗ if (num_devices > MAX_NODE_GPUS) {
98 ✗ warning("%zu devices registered within a node but MAX_NODE_GPUS=%d. "
99 "If you think this is an error, please report bug.",
100 num_devices, MAX_NODE_GPUS);
101 }
102
103 ✗ return DLB_SUCCESS;
104 }
105
106
107 // Called from talp core
108 ✗ void talp_gpu_finalize(void) {
109
110 ✗ if (gpu_backend_api != NULL) {
111
112 ✗ gpu_backend_api->stop();
113 ✗ gpu_backend_api->finalize();
114
115 ✗ free(devices);
116 ✗ devices = NULL;
117 ✗ num_devices = 0;
118
119 ✗ talp_backend_manager_unload_gpu_backend();
120 ✗ gpu_backend_api = NULL;
121 }
122 }
123
124
125 ✗ uint64_t talp_gpu_local_to_unique_id(uint32_t local_id) {
126
127 ✗ for (size_t i = 0; i < num_devices; ++i) {
128 ✗ if (devices[i].local_id == local_id) {
129 ✗ return devices[i].node_unique_id;
130 }
131 }
132
133 ✗ return ULLONG_MAX;
134 }
135
136
137 // Called from GPU backend plugin: CPU enters GPU runtime
138 ✗ void talp_gpu_enter_runtime(void) {
139
140 /* Observer and unknown threads may call GPU offload functions, but TALP must ignore them */
141 ✗ if (unlikely(!thread_is_profiled())) return;
142
143 ✗ talp_info_t *talp_info = thread_spd->talp_info;
144 ✗ if (talp_info) {
145 /* Update sample */
146 ✗ talp_sample_update(talp_info);
147
148 /* Into Sync call -> not_useful_gpu */
149 ✗ talp_sample_set_state(talp_info, TALP_STATE_NOT_USEFUL_GPU);
150 }
151 }
152
153
154 // Called from GPU backend plugin: CPU exits GPU runtime
155 ✗ void talp_gpu_exit_runtime(void) {
156
157 /* Observer and unknown threads may call GPU offload functions, but TALP must ignore them */
158 ✗ if (unlikely(!thread_is_profiled())) return;
159
160 ✗ talp_info_t *talp_info = thread_spd->talp_info;
161 ✗ if (talp_info) {
162 /* Update sample */
163 ✗ talp_sample_update(talp_info);
164
165 /* Add statistic */
166 ✗ talp_sample_t *sample = talp_sample_get(talp_info);
167 ✗ ++sample->stats.num_gpu_runtime_calls;
168
169 /* Out of Sync call -> useful */
170 ✗ talp_sample_set_state(talp_info, TALP_STATE_USEFUL);
171
172 /* Only when needed, update all regions */
173 ✗ if (talp_info->flags.external_profiler
174 ✗ && thread_is_main_sequential()) {
175 ✗ talp_aggregate_samples_to_regions(talp_info);
176 }
177 }
178 }
179
180
181 // Called from core
182 ✗ void talp_gpu_collect(gpu_timers_t *out, size_t capacity, uint64_t *out_mask) {
183
184 ✗ ensure(thread_is_main(), "Non-main thread collecting GPU measurements. Please report bug.");
185
186 ✗ gpu_backend_api->gpu.collect(out, capacity, out_mask);
187 }
188