[OMPT] Add callback for omp_target_memset calls (#194168)
OpenMP v6.0 added new enum values to `ompt_callback_target_data_op_t` for communicating `memset` events. Add a corresponding callback invokation to `omp_target_memset` calls. Expand the tests to ensure correct behavior. Signed-off-by: Jan André Reuter <j.reuter@fz-juelich.de>
This commit is contained in:
parent
ea4cd9228f
commit
2c8ca9679e
7 changed files with 279 additions and 0 deletions
|
|
@ -621,6 +621,7 @@ implementation.
|
|||
| OMPT: ompt_target_data_transfer(_async) | :part:`partial` | :good:`N/A` | Enum: https://github.com/llvm/llvm-project/pull/195829 |
|
||||
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
|
||||
| OMPT: ompt_target_data_memset(_async) | :part:`partial` | :good:`N/A` | Enum: https://github.com/llvm/llvm-project/pull/195829 |
|
||||
| | | | Callbacks: https://github.com/llvm/llvm-project/pull/194168 |
|
||||
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
|
||||
| OMPT: workdistribute work callback enum | :part:`partial` | :good:`N/A` | Enum: https://github.com/llvm/llvm-project/pull/195829 |
|
||||
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
|
||||
|
|
|
|||
|
|
@ -126,6 +126,14 @@ public:
|
|||
void endTargetDisassociatePointer(int64_t DeviceId, void *HstPtrBegin,
|
||||
void *TgtPtrBegin, size_t Size, void *Code);
|
||||
|
||||
/// Top-level function for invoking callback before target memset API
|
||||
void beginTargetMemset(int64_t DeviceId, void *HostPtrBegin,
|
||||
void *TgtPtrBegin, size_t Size, void *Code);
|
||||
|
||||
/// Top-level function for invoking callback after target memset API
|
||||
void endTargetMemset(int64_t DeviceId, void *HostPtrBegin, void *TgtPtrBegin,
|
||||
size_t Size, void *Code);
|
||||
|
||||
// Target kernel callbacks
|
||||
|
||||
/// Top-level function for invoking callback before target construct
|
||||
|
|
@ -166,6 +174,11 @@ public:
|
|||
std::mem_fn(&Interface::beginTargetDisassociatePointer),
|
||||
std::mem_fn(&Interface::endTargetDisassociatePointer));
|
||||
|
||||
if constexpr (OpType == ompt_target_data_memset ||
|
||||
OpType == ompt_target_data_memset_async)
|
||||
return std::make_pair(std::mem_fn(&Interface::beginTargetMemset),
|
||||
std::mem_fn(&Interface::endTargetMemset));
|
||||
|
||||
llvm_unreachable("Unhandled target data operation type!");
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -477,6 +477,11 @@ EXTERN void *omp_target_memset(void *Ptr, int ByteVal, size_t NumBytes,
|
|||
ODBG(ODT_Interface) << "filling memory on host via memset";
|
||||
memset(Ptr, ByteVal, NumBytes); // ignore return value, memset() cannot fail
|
||||
} else {
|
||||
OMPT_IF_BUILT(InterfaceRAII TargetMemsetRAII(
|
||||
RegionInterface.getCallbacks<ompt_target_data_memset>(), DeviceNum,
|
||||
nullptr, const_cast<void *>(Ptr), NumBytes,
|
||||
__builtin_return_address(0)));
|
||||
|
||||
// TODO: replace the omp_target_memset() slow path with the fast path.
|
||||
// That will require the ability to execute a kernel from within
|
||||
// libomptarget.so (which we do not have at the moment).
|
||||
|
|
|
|||
|
|
@ -387,6 +387,33 @@ void Interface::endTargetDisassociatePointer(int64_t DeviceId,
|
|||
}
|
||||
}
|
||||
|
||||
void Interface::beginTargetMemset(int64_t DeviceId, void *HostPtrBegin,
|
||||
void *TgtPtrBegin, size_t Size, void *Code) {
|
||||
beginTargetDataOperation();
|
||||
if (ompt_callback_target_data_op_emi_fn) {
|
||||
ompt_callback_target_data_op_emi_fn(
|
||||
ompt_scope_begin, TargetTaskData, &TargetData, &HostOpId,
|
||||
ompt_target_data_memset, HostPtrBegin, omp_initial_device, TgtPtrBegin,
|
||||
DeviceId, Size, Code);
|
||||
} else if (ompt_callback_target_data_op_fn) {
|
||||
HostOpId = createOpId();
|
||||
ompt_callback_target_data_op_fn(
|
||||
TargetData.value, HostOpId, ompt_target_data_memset, HostPtrBegin,
|
||||
omp_initial_device, TgtPtrBegin, DeviceId, Size, Code);
|
||||
}
|
||||
}
|
||||
|
||||
void Interface::endTargetMemset(int64_t DeviceId, void *HostPtrBegin,
|
||||
void *TgtPtrBegin, size_t Size, void *Code) {
|
||||
if (ompt_callback_target_data_op_emi_fn) {
|
||||
ompt_callback_target_data_op_emi_fn(
|
||||
ompt_scope_end, TargetTaskData, &TargetData, &HostOpId,
|
||||
ompt_target_data_memset, HostPtrBegin, omp_initial_device, TgtPtrBegin,
|
||||
DeviceId, Size, Code);
|
||||
}
|
||||
endTargetDataOperation();
|
||||
}
|
||||
|
||||
void Interface::beginTarget(int64_t DeviceId, void *Code) {
|
||||
beginTargetRegion();
|
||||
if (ompt_callback_target_emi_fn) {
|
||||
|
|
|
|||
76
offload/test/ompt/target_memset.c
Normal file
76
offload/test/ompt/target_memset.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// clang-format off
|
||||
// RUN: %libomptarget-compile-run-and-check-generic
|
||||
// REQUIRES: ompt
|
||||
// REQUIRES: gpu
|
||||
// clang-format on
|
||||
|
||||
/*
|
||||
* Verify that for the target OpenMP APIs, the return address is non-null and
|
||||
* distinct.
|
||||
*/
|
||||
|
||||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "register_non_emi.h"
|
||||
|
||||
int main() {
|
||||
int d = omp_get_default_device();
|
||||
int id = omp_get_initial_device();
|
||||
int q[128], i;
|
||||
void *p;
|
||||
void *result;
|
||||
|
||||
if (d < 0 || d >= omp_get_num_devices())
|
||||
d = id;
|
||||
|
||||
p = omp_target_alloc(130 * sizeof(int), d);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
q[i] = i;
|
||||
|
||||
result = omp_target_memset(p, 0, 130 * sizeof(int), d);
|
||||
if (result != p) {
|
||||
abort();
|
||||
}
|
||||
|
||||
int q2[128];
|
||||
for (i = 0; i < 128; ++i)
|
||||
q2[i] = i;
|
||||
if (omp_target_memcpy_async(q2, p, 128 * sizeof(int), 0, sizeof(int), id, d,
|
||||
0, NULL))
|
||||
abort();
|
||||
|
||||
#pragma omp taskwait
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
if (q2[i] != 0)
|
||||
abort();
|
||||
|
||||
omp_target_free(p, d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_alloc
|
||||
/// CHECK-SAME: src_device_num=[[HOST:-1]]
|
||||
/// CHECK-SAME: dest_device_num=[[DEVICE:[0-9]+]]
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK: code=[[CODE1:0x[0-f]+]]
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_memset
|
||||
/// CHECK-SAME: src_device_num=[[HOST]] {{.+}} dest_device_num=[[DEVICE]]
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK-NOT: code=[[CODE1]]
|
||||
/// CHECK: code=[[CODE2:0x[0-f]+]]
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_transfer_from_device
|
||||
/// CHECK-SAME: src_device_num=[[DEVICE]] {{.+}} dest_device_num=[[HOST]]
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK-NOT: code=[[CODE2]]
|
||||
/// CHECK: code=[[CODE3:0x[0-f]+]]
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_delete
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK-NOT: code=[[CODE3]]
|
||||
79
offload/test/ompt/target_memset_async.c
Normal file
79
offload/test/ompt/target_memset_async.c
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// clang-format off
|
||||
// RUN: %libomptarget-compile-run-and-check-generic
|
||||
// REQUIRES: ompt
|
||||
// REQUIRES: gpu
|
||||
// clang-format on
|
||||
|
||||
/*
|
||||
* Verify that for the target OpenMP APIs, the return address is non-null and
|
||||
* distinct.
|
||||
*/
|
||||
|
||||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "register_non_emi.h"
|
||||
|
||||
int main() {
|
||||
int d = omp_get_default_device();
|
||||
int id = omp_get_initial_device();
|
||||
int q[128], i;
|
||||
void *p;
|
||||
void *result;
|
||||
|
||||
if (d < 0 || d >= omp_get_num_devices())
|
||||
d = id;
|
||||
|
||||
p = omp_target_alloc(130 * sizeof(int), d);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
q[i] = i;
|
||||
|
||||
result = omp_target_memset_async(p, 0, 130 * sizeof(int), d, 0, NULL);
|
||||
|
||||
#pragma omp taskwait
|
||||
|
||||
if (result != p) {
|
||||
abort();
|
||||
}
|
||||
|
||||
int q2[128];
|
||||
for (i = 0; i < 128; ++i)
|
||||
q2[i] = i;
|
||||
if (omp_target_memcpy_async(q2, p, 128 * sizeof(int), 0, sizeof(int), id, d,
|
||||
0, NULL))
|
||||
abort();
|
||||
|
||||
#pragma omp taskwait
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
if (q2[i] != 0)
|
||||
abort();
|
||||
|
||||
omp_target_free(p, d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_alloc
|
||||
/// CHECK-SAME: src_device_num=[[HOST:-1]]
|
||||
/// CHECK-SAME: dest_device_num=[[DEVICE:[0-9]+]]
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK: code=[[CODE1:0x[0-f]+]]
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_memset
|
||||
/// CHECK-SAME: src_device_num=[[HOST]] {{.+}} dest_device_num=[[DEVICE]]
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK-NOT: code=[[CODE1]]
|
||||
/// CHECK: code=[[CODE2:0x[0-f]+]]
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_transfer_from_device
|
||||
/// CHECK-SAME: src_device_num=[[DEVICE]] {{.+}} dest_device_num=[[HOST]]
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK-NOT: code=[[CODE2]]
|
||||
/// CHECK: code=[[CODE3:0x[0-f]+]]
|
||||
/// CHECK: Callback DataOp: target_id=[[TARGET_ID:[0-9]+]] host_op_id=[[HOST_OP_ID:[0-9]+]] optype=ompt_target_data_delete
|
||||
/// CHECK-NOT: code=(nil)
|
||||
/// CHECK-NOT: code=[[CODE3]]
|
||||
78
offload/test/ompt/target_memset_emi.c
Normal file
78
offload/test/ompt/target_memset_emi.c
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
// clang-format off
|
||||
// RUN: %libomptarget-compile-run-and-check-generic
|
||||
// REQUIRES: ompt
|
||||
// REQUIRES: gpu
|
||||
// clang-format on
|
||||
|
||||
/*
|
||||
* Verify correct callback sequence for memset API call.
|
||||
*/
|
||||
|
||||
#include <omp.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "callbacks.h"
|
||||
#include "register_emi.h"
|
||||
|
||||
int main() {
|
||||
int d = omp_get_default_device();
|
||||
int id = omp_get_initial_device();
|
||||
int q[128], i;
|
||||
void *p;
|
||||
void *result;
|
||||
|
||||
if (d < 0 || d >= omp_get_num_devices())
|
||||
d = id;
|
||||
|
||||
p = omp_target_alloc(130 * sizeof(int), d);
|
||||
if (p == NULL)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < 128; i++)
|
||||
q[i] = i;
|
||||
|
||||
result = omp_target_memset(p, 0, 130 * sizeof(int), d);
|
||||
if (result != p) {
|
||||
abort();
|
||||
}
|
||||
|
||||
int q2[128];
|
||||
for (i = 0; i < 128; ++i)
|
||||
q2[i] = i;
|
||||
if (omp_target_memcpy_async(q2, p, 128 * sizeof(int), 0, sizeof(int), id, d,
|
||||
0, NULL))
|
||||
abort();
|
||||
|
||||
#pragma omp taskwait
|
||||
|
||||
for (i = 0; i < 128; ++i)
|
||||
if (q2[i] != 0)
|
||||
abort();
|
||||
|
||||
omp_target_free(p, d);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
|
||||
/// CHECK: Callback Init:
|
||||
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_alloc
|
||||
/// CHECK-SAME: src_device_num=[[HOST:-1]]
|
||||
/// CHECK-SAME: dest_device_num=[[DEVICE:[0-9]+]]
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_alloc {{.+}} src_device_num=[[HOST]] {{.+}} dest_device_num=[[DEVICE]]
|
||||
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_memset {{.+}} src_device_num=[[HOST]] {{.+}} dest_device_num=[[DEVICE]]
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_memset {{.+}} src_device_num=[[HOST]] {{.+}} dest_device_num=[[DEVICE]]
|
||||
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_transfer_from_device {{.+}} src_device_num=[[DEVICE]] {{.+}} dest_device_num=[[HOST]]
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_transfer_from_device {{.+}} src_device_num=[[DEVICE]] {{.+}} dest_device_num=[[HOST]]
|
||||
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_begin optype=ompt_target_data_delete {{.+}} src_device_num=[[DEVICE]]
|
||||
/// CHECK: Callback DataOp EMI: endpoint=ompt_scope_end optype=ompt_target_data_delete {{.+}} src_device_num=[[DEVICE]]
|
||||
|
||||
/// CHECK: Callback Fini:
|
||||
|
||||
// clang-format on
|
||||
Loading…
Reference in a new issue