1 | /******************************************************************************* |
2 | * Copyright 2021 Intel Corporation |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | *******************************************************************************/ |
16 | |
17 | #include <CL/cl.h> |
18 | |
19 | #include "common/guard_manager.hpp" |
20 | #include "gpu/ocl/ocl_usm_memory_storage.hpp" |
21 | #include "gpu/ocl/ocl_usm_utils.hpp" |
22 | |
23 | namespace dnnl { |
24 | namespace impl { |
25 | namespace gpu { |
26 | namespace ocl { |
27 | |
28 | struct map_usm_tag; |
29 | |
30 | status_t ocl_usm_memory_storage_t::map_data( |
31 | void **mapped_ptr, stream_t *stream, size_t size) const { |
32 | |
33 | if (is_host_accessible()) { |
34 | *mapped_ptr = usm_ptr(); |
35 | return status::success; |
36 | } |
37 | |
38 | if (!usm_ptr() || size == 0) { |
39 | *mapped_ptr = nullptr; |
40 | return status::success; |
41 | } |
42 | |
43 | if (!stream) CHECK(engine()->get_service_stream(stream)); |
44 | |
45 | void *host_ptr = usm::malloc_host(engine(), size); |
46 | if (!host_ptr) return status::out_of_memory; |
47 | |
48 | auto leak_guard = decltype(usm_ptr_)( |
49 | host_ptr, [=](void *p) { usm::free(engine(), p); }); |
50 | CHECK(usm::memcpy(stream, host_ptr, usm_ptr(), size)); |
51 | CHECK(stream->wait()); |
52 | leak_guard.release(); |
53 | |
54 | auto unmap_callback = [=]() mutable { |
55 | usm::memcpy(stream, usm_ptr(), host_ptr, size); |
56 | stream->wait(); |
57 | usm::free(engine(), host_ptr); |
58 | }; |
59 | |
60 | auto &guard_manager = guard_manager_t<map_usm_tag>::instance(); |
61 | |
62 | *mapped_ptr = host_ptr; |
63 | return guard_manager.enter(this, unmap_callback); |
64 | } |
65 | |
66 | status_t ocl_usm_memory_storage_t::unmap_data( |
67 | void *mapped_ptr, stream_t *stream) const { |
68 | if (!mapped_ptr || is_host_accessible()) return status::success; |
69 | |
70 | auto &guard_manager = guard_manager_t<map_usm_tag>::instance(); |
71 | return guard_manager.exit(this); |
72 | } |
73 | |
74 | std::unique_ptr<memory_storage_t> ocl_usm_memory_storage_t::get_sub_storage( |
75 | size_t offset, size_t size) const { |
76 | void *sub_ptr = usm_ptr_ |
77 | ? reinterpret_cast<uint8_t *>(usm_ptr_.get()) + offset |
78 | : nullptr; |
79 | |
80 | auto storage = utils::make_unique<ocl_usm_memory_storage_t>(engine()); |
81 | if (!storage) return nullptr; |
82 | auto status = storage->init(memory_flags_t::use_runtime_ptr, size, sub_ptr); |
83 | if (status != status::success) return nullptr; |
84 | // XXX: Clang has a bug that prevents implicit conversion. |
85 | return std::unique_ptr<memory_storage_t>(storage.release()); |
86 | } |
87 | |
88 | std::unique_ptr<memory_storage_t> ocl_usm_memory_storage_t::clone() const { |
89 | auto storage = utils::make_unique<ocl_usm_memory_storage_t>(engine()); |
90 | if (!storage) return nullptr; |
91 | |
92 | auto status = storage->init(memory_flags_t::use_runtime_ptr, 0, nullptr); |
93 | if (status != status::success) return nullptr; |
94 | |
95 | storage->usm_ptr_ = decltype(usm_ptr_)(usm_ptr_.get(), [](void *) {}); |
96 | storage->usm_kind_ = usm_kind_; |
97 | |
98 | // XXX: Clang has a bug that prevents implicit conversion. |
99 | return std::unique_ptr<memory_storage_t>(storage.release()); |
100 | } |
101 | |
102 | } // namespace ocl |
103 | } // namespace gpu |
104 | } // namespace impl |
105 | } // namespace dnnl |
106 | |