@@ -167,13 +167,26 @@ static umf_result_t numa_get_capacity(void *memTarget, size_t *capacity) {
167
167
return UMF_RESULT_SUCCESS ;
168
168
}
169
169
170
- static umf_result_t numa_get_bandwidth (void * srcMemoryTarget ,
171
- void * dstMemoryTarget ,
172
- size_t * bandwidth ) {
173
- if (!srcMemoryTarget || !dstMemoryTarget || !bandwidth ) {
174
- return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
170
+ typedef enum memattr_type {
171
+ MEMATTR_TYPE_BANDWIDTH ,
172
+ MEMATTR_TYPE_LATENCY
173
+ } memattr_type ;
174
+
175
+ static size_t memattr_get_worst_value (memattr_type type ) {
176
+ switch (type ) {
177
+ case MEMATTR_TYPE_BANDWIDTH :
178
+ return 0 ;
179
+ case MEMATTR_TYPE_LATENCY :
180
+ return SIZE_MAX ;
181
+ default :
182
+ assert (0 ); // Should not be reachable
183
+ return 0 ;
175
184
}
185
+ }
176
186
187
+ static umf_result_t query_attribute_value (void * srcMemoryTarget ,
188
+ void * dstMemoryTarget , size_t * value ,
189
+ memattr_type type ) {
177
190
hwloc_topology_t topology = umfGetTopology ();
178
191
if (!topology ) {
179
192
return UMF_RESULT_ERROR_NOT_SUPPORTED ;
@@ -195,23 +208,75 @@ static umf_result_t numa_get_bandwidth(void *srcMemoryTarget,
195
208
196
209
// Given NUMA nodes aren't local, HWLOC returns an error in such case.
197
210
if (!hwloc_bitmap_intersects (srcNumaNode -> cpuset , dstNumaNode -> cpuset )) {
198
- * bandwidth = 0 ;
211
+ // Since we want to skip such query, we return the worst possible
212
+ // value for given memory attribute.
213
+ * value = memattr_get_worst_value (type );
199
214
return UMF_RESULT_SUCCESS ;
200
215
}
201
216
217
+ enum hwloc_memattr_id_e hwlocMemAttrType = INT_MAX ;
218
+ switch (type ) {
219
+ case MEMATTR_TYPE_BANDWIDTH :
220
+ hwlocMemAttrType = HWLOC_MEMATTR_ID_BANDWIDTH ;
221
+ break ;
222
+ case MEMATTR_TYPE_LATENCY :
223
+ hwlocMemAttrType = HWLOC_MEMATTR_ID_LATENCY ;
224
+ break ;
225
+ default :
226
+ assert (0 ); // Shouldn't be reachable.
227
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
228
+ }
229
+
202
230
struct hwloc_location initiator = {.location .cpuset = srcNumaNode -> cpuset ,
203
231
.type = HWLOC_LOCATION_TYPE_CPUSET };
204
- hwloc_uint64_t value = 0 ;
205
- int ret = hwloc_memattr_get_value (topology , HWLOC_MEMATTR_ID_BANDWIDTH ,
206
- dstNumaNode , & initiator , 0 , & value );
232
+
233
+ hwloc_uint64_t memAttrValue = 0 ;
234
+ int ret = hwloc_memattr_get_value (topology , hwlocMemAttrType , dstNumaNode ,
235
+ & initiator , 0 , & memAttrValue );
207
236
if (ret ) {
208
- LOG_ERR ("Retrieving bandwidth for initiator node %u to node %u failed." ,
209
- srcNumaNode -> os_index , dstNumaNode -> os_index );
210
237
return (errno == EINVAL ) ? UMF_RESULT_ERROR_NOT_SUPPORTED
211
238
: UMF_RESULT_ERROR_UNKNOWN ;
212
239
}
213
240
214
- * bandwidth = value ;
241
+ * value = memAttrValue ;
242
+
243
+ return UMF_RESULT_SUCCESS ;
244
+ }
245
+
246
+ static umf_result_t numa_get_bandwidth (void * srcMemoryTarget ,
247
+ void * dstMemoryTarget ,
248
+ size_t * bandwidth ) {
249
+ if (!srcMemoryTarget || !dstMemoryTarget || !bandwidth ) {
250
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
251
+ }
252
+
253
+ umf_result_t ret = query_attribute_value (srcMemoryTarget , dstMemoryTarget ,
254
+ bandwidth , MEMATTR_TYPE_BANDWIDTH );
255
+ if (ret ) {
256
+ LOG_ERR ("Retrieving bandwidth for initiator node %u to node %u failed." ,
257
+ ((struct numa_memory_target_t * )srcMemoryTarget )-> physical_id ,
258
+ ((struct numa_memory_target_t * )dstMemoryTarget )-> physical_id );
259
+ return ret ;
260
+ }
261
+
262
+ return UMF_RESULT_SUCCESS ;
263
+ }
264
+
265
+ static umf_result_t numa_get_latency (void * srcMemoryTarget ,
266
+ void * dstMemoryTarget , size_t * latency ) {
267
+ if (!srcMemoryTarget || !dstMemoryTarget || !latency ) {
268
+ return UMF_RESULT_ERROR_INVALID_ARGUMENT ;
269
+ }
270
+
271
+ umf_result_t ret = query_attribute_value (srcMemoryTarget , dstMemoryTarget ,
272
+ latency , MEMATTR_TYPE_LATENCY );
273
+ if (ret ) {
274
+ LOG_ERR ("Retrieving latency for initiator node %u to node %u failed." ,
275
+ ((struct numa_memory_target_t * )srcMemoryTarget )-> physical_id ,
276
+ ((struct numa_memory_target_t * )dstMemoryTarget )-> physical_id );
277
+ return ret ;
278
+ }
279
+
215
280
return UMF_RESULT_SUCCESS ;
216
281
}
217
282
@@ -223,5 +288,6 @@ struct umf_memory_target_ops_t UMF_MEMORY_TARGET_NUMA_OPS = {
223
288
.clone = numa_clone ,
224
289
.get_capacity = numa_get_capacity ,
225
290
.get_bandwidth = numa_get_bandwidth ,
291
+ .get_latency = numa_get_latency ,
226
292
.memory_provider_create_from_memspace =
227
293
numa_memory_provider_create_from_memspace };
0 commit comments