Skip to content

Commit 8448f78

Browse files
committed
[CTS][L0 v2] adjust urEnqueueMemBufferMap
to match SYCL expectations. When pHost is set in buffer properties, urEnqueueMemBufferMap should map memory to that pointer (instead of creating a new allocation).
1 parent f87cb7e commit 8448f78

File tree

4 files changed

+102
-46
lines changed

4 files changed

+102
-46
lines changed

source/adapters/level_zero/v2/memory.cpp

Lines changed: 49 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ ur_discrete_mem_handle_t::ur_discrete_mem_handle_t(
209209
device_access_mode_t accessMode)
210210
: ur_mem_handle_t_(hContext, size, accessMode),
211211
deviceAllocations(hContext->getPlatform()->getNumDevices()),
212-
activeAllocationDevice(nullptr), hostAllocations() {
212+
activeAllocationDevice(nullptr), mapToPtr(hostPtr), hostAllocations() {
213213
if (hostPtr) {
214214
auto initialDevice = hContext->getDevices()[0];
215215
UR_CALL_THROWS(migrateBufferTo(initialDevice, hostPtr, size));
@@ -246,12 +246,18 @@ ur_discrete_mem_handle_t::~ur_discrete_mem_handle_t() {
246246
if (!activeAllocationDevice || !writeBackPtr)
247247
return;
248248

249-
auto srcPtr = ur_cast<char *>(
250-
deviceAllocations[activeAllocationDevice->Id.value()].get());
249+
auto srcPtr = getActiveDeviceAlloc();
251250
synchronousZeCopy(hContext, activeAllocationDevice, writeBackPtr, srcPtr,
252251
getSize());
253252
}
254253

254+
void *ur_discrete_mem_handle_t::getActiveDeviceAlloc(size_t offset) {
255+
assert(activeAllocationDevice);
256+
return ur_cast<char *>(
257+
deviceAllocations[activeAllocationDevice->Id.value()].get()) +
258+
offset;
259+
}
260+
255261
void *ur_discrete_mem_handle_t::getDevicePtr(
256262
ur_device_handle_t hDevice, device_access_mode_t access, size_t offset,
257263
size_t size, std::function<void(void *src, void *dst, size_t)> migrate) {
@@ -272,10 +278,8 @@ void *ur_discrete_mem_handle_t::getDevicePtr(
272278
hDevice = activeAllocationDevice;
273279
}
274280

275-
char *ptr;
276281
if (activeAllocationDevice == hDevice) {
277-
ptr = ur_cast<char *>(deviceAllocations[hDevice->Id.value()].get());
278-
return ptr + offset;
282+
return getActiveDeviceAlloc(offset);
279283
}
280284

281285
auto &p2pDevices = hContext->getP2PDevices(hDevice);
@@ -288,9 +292,7 @@ void *ur_discrete_mem_handle_t::getDevicePtr(
288292
}
289293

290294
// TODO: see if it's better to migrate the memory to the specified device
291-
return ur_cast<char *>(
292-
deviceAllocations[activeAllocationDevice->Id.value()].get()) +
293-
offset;
295+
return getActiveDeviceAlloc(offset);
294296
}
295297

296298
void *ur_discrete_mem_handle_t::mapHostPtr(
@@ -299,55 +301,60 @@ void *ur_discrete_mem_handle_t::mapHostPtr(
299301
TRACK_SCOPE_LATENCY("ur_discrete_mem_handle_t::mapHostPtr");
300302
// TODO: use async alloc?
301303

302-
void *ptr;
303-
UR_CALL_THROWS(hContext->getDefaultUSMPool()->allocate(
304-
hContext, nullptr, nullptr, UR_USM_TYPE_HOST, size, &ptr));
304+
void *ptr = mapToPtr;
305+
if (!ptr) {
306+
UR_CALL_THROWS(hContext->getDefaultUSMPool()->allocate(
307+
hContext, nullptr, nullptr, UR_USM_TYPE_HOST, size, &ptr));
308+
}
305309

306-
hostAllocations.emplace_back(ptr, size, offset, flags);
310+
usm_unique_ptr_t mappedPtr =
311+
usm_unique_ptr_t(ptr, [ownsAlloc = bool(mapToPtr), this](void *p) {
312+
if (ownsAlloc) {
313+
UR_CALL_THROWS(hContext->getDefaultUSMPool()->free(p));
314+
}
315+
});
316+
317+
hostAllocations.emplace_back(std::move(mappedPtr), size, offset, flags);
307318

308319
if (activeAllocationDevice && (flags & UR_MAP_FLAG_READ)) {
309-
auto srcPtr =
310-
ur_cast<char *>(
311-
deviceAllocations[activeAllocationDevice->Id.value()].get()) +
312-
offset;
313-
migrate(srcPtr, hostAllocations.back().ptr, size);
320+
auto srcPtr = getActiveDeviceAlloc(offset);
321+
migrate(srcPtr, hostAllocations.back().ptr.get(), size);
314322
}
315323

316-
return hostAllocations.back().ptr;
324+
return hostAllocations.back().ptr.get();
317325
}
318326

319327
void ur_discrete_mem_handle_t::unmapHostPtr(
320328
void *pMappedPtr,
321329
std::function<void(void *src, void *dst, size_t)> migrate) {
322330
TRACK_SCOPE_LATENCY("ur_discrete_mem_handle_t::unmapHostPtr");
323331

324-
for (auto &hostAllocation : hostAllocations) {
325-
if (hostAllocation.ptr == pMappedPtr) {
326-
void *devicePtr = nullptr;
327-
if (activeAllocationDevice) {
328-
devicePtr =
329-
ur_cast<char *>(
330-
deviceAllocations[activeAllocationDevice->Id.value()].get()) +
331-
hostAllocation.offset;
332-
} else if (!(hostAllocation.flags &
333-
UR_MAP_FLAG_WRITE_INVALIDATE_REGION)) {
334-
devicePtr = ur_cast<char *>(getDevicePtr(
335-
hContext->getDevices()[0], device_access_mode_t::read_only,
336-
hostAllocation.offset, hostAllocation.size, migrate));
337-
}
332+
auto hostAlloc =
333+
std::find_if(hostAllocations.begin(), hostAllocations.end(),
334+
[pMappedPtr](const host_allocation_desc_t &desc) {
335+
return desc.ptr.get() == pMappedPtr;
336+
});
338337

339-
if (devicePtr) {
340-
migrate(hostAllocation.ptr, devicePtr, hostAllocation.size);
341-
}
338+
if (hostAlloc == hostAllocations.end()) {
339+
throw UR_RESULT_ERROR_INVALID_ARGUMENT;
340+
}
342341

343-
// TODO: use async free here?
344-
UR_CALL_THROWS(hContext->getDefaultUSMPool()->free(hostAllocation.ptr));
345-
return;
346-
}
342+
bool shouldMigrateToDevice =
343+
!(hostAlloc->flags & UR_MAP_FLAG_WRITE_INVALIDATE_REGION);
344+
345+
if (!activeAllocationDevice && shouldMigrateToDevice) {
346+
allocateOnDevice(hContext->getDevices()[0], getSize());
347+
}
348+
349+
// TODO: tests require that memory is migrated even for
350+
// UR_MAP_FLAG_WRITE_INVALIDATE_REGION when there is an active device
351+
// allocation. is this correct?
352+
if (activeAllocationDevice) {
353+
migrate(hostAlloc->ptr.get(), getActiveDeviceAlloc(hostAlloc->offset),
354+
hostAlloc->size);
347355
}
348356

349-
// No mapping found
350-
throw UR_RESULT_ERROR_INVALID_ARGUMENT;
357+
hostAllocations.erase(hostAlloc);
351358
}
352359

353360
static bool useHostBuffer(ur_context_handle_t hContext) {

source/adapters/level_zero/v2/memory.hpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,11 +98,11 @@ struct ur_integrated_mem_handle_t : public ur_mem_handle_t_ {
9898
};
9999

100100
struct host_allocation_desc_t {
101-
host_allocation_desc_t(void *ptr, size_t size, size_t offset,
101+
host_allocation_desc_t(usm_unique_ptr_t ptr, size_t size, size_t offset,
102102
ur_map_flags_t flags)
103-
: ptr(ptr), size(size), offset(offset), flags(flags) {}
103+
: ptr(std::move(ptr)), size(size), offset(offset), flags(flags) {}
104104

105-
void *ptr;
105+
usm_unique_ptr_t ptr;
106106
size_t size;
107107
size_t offset;
108108
ur_map_flags_t flags;
@@ -146,10 +146,13 @@ struct ur_discrete_mem_handle_t : public ur_mem_handle_t_ {
146146
// If not null, copy the buffer content back to this memory on release.
147147
void *writeBackPtr = nullptr;
148148

149+
// If not null, mapHostPtr should map memory to this ptr
150+
void *mapToPtr = nullptr;
151+
149152
std::vector<host_allocation_desc_t> hostAllocations;
150153

154+
void *getActiveDeviceAlloc(size_t offset = 0);
151155
void *allocateOnDevice(ur_device_handle_t hDevice, size_t size);
152-
153156
ur_result_t migrateBufferTo(ur_device_handle_t hDevice, void *src,
154157
size_t size);
155158
};

test/adapters/level_zero/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,14 @@ function(add_adapter_tests adapter)
8686
ur_umf
8787
)
8888
endif()
89+
90+
add_adapter_test(${adapter}_mem_buffer_map
91+
FIXTURE DEVICES
92+
SOURCES
93+
urEnqueueMemBufferMapHostPtr.cpp
94+
ENVIRONMENT
95+
"UR_ADAPTERS_FORCE_LOAD=\"$<TARGET_FILE:ur_adapter_${adapter}>\""
96+
)
8997
endfunction()
9098

9199
if(UR_BUILD_ADAPTER_L0)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (C) 2023 Intel Corporation
2+
// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM
3+
// Exceptions. See LICENSE.TXT
4+
//
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
#include "../../enqueue/helpers.h"
7+
#include <uur/fixtures.h>
8+
#include <uur/known_failure.h>
9+
#include <uur/raii.h>
10+
11+
using urEnqueueMemBufferMapTestWithParamL0 =
12+
uur::urMemBufferQueueTestWithParam<uur::mem_buffer_test_parameters_t>;
13+
14+
UUR_DEVICE_TEST_SUITE_P(
15+
urEnqueueMemBufferMapTestWithParamL0,
16+
::testing::ValuesIn(uur::mem_buffer_test_parameters),
17+
uur::printMemBufferTestString<urEnqueueMemBufferMapTestWithParamL0>);
18+
19+
TEST_P(urEnqueueMemBufferMapTestWithParamL0, MapWithHostPtr) {
20+
uur::raii::Mem buffer;
21+
22+
char *ptr = new char[4096];
23+
24+
ur_buffer_properties_t props;
25+
props.pHost = ptr;
26+
27+
ASSERT_SUCCESS(urMemBufferCreate(context, UR_MEM_FLAG_USE_HOST_POINTER, 4096,
28+
&props, buffer.ptr()));
29+
30+
void *mappedPtr = nullptr;
31+
ASSERT_SUCCESS(urEnqueueMemBufferMap(
32+
queue, buffer.get(), true, UR_MAP_FLAG_READ | UR_MAP_FLAG_WRITE, 0, 4096,
33+
0, nullptr, nullptr, reinterpret_cast<void **>(&mappedPtr)));
34+
35+
ASSERT_EQ(ptr, mappedPtr);
36+
37+
delete[] ptr;
38+
}

0 commit comments

Comments
 (0)