Skip to content

Commit f568c44

Browse files
committed
Add wrapper for clEnqueueSVMMigrateMem()
1 parent 35aa665 commit f568c44

File tree

2 files changed

+124
-0
lines changed

2 files changed

+124
-0
lines changed

include/boost/compute/command_queue.hpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,13 @@ class command_queue
9797
#endif
9898
};
9999

100+
#ifdef BOOST_COMPUTE_CL_VERSION_1_2
101+
enum mem_migration_flags {
102+
migrate_to_host = CL_MIGRATE_MEM_OBJECT_HOST,
103+
migrate_content_undefined = CL_MIGRATE_MEM_OBJECT_CONTENT_UNDEFINED
104+
};
105+
#endif // BOOST_COMPUTE_CL_VERSION_1_2
106+
100107
/// Creates a null command queue.
101108
command_queue()
102109
: m_queue(0)
@@ -1810,6 +1817,80 @@ class command_queue
18101817
}
18111818
#endif // BOOST_COMPUTE_CL_VERSION_2_0
18121819

1820+
#if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1821+
/// Enqueues a command to indicate which device a set of ranges of SVM allocations
1822+
/// should be associated with. The pair \p svm_ptrs[i] and \p sizes[i] together define
1823+
/// the starting address and number of bytes in a range to be migrated.
1824+
///
1825+
/// If \p sizes is empty, then that means every allocation containing any \p svm_ptrs[i]
1826+
/// is to be migrated. Also, if \p sizes[i] is zero, then the entire allocation containing
1827+
/// \p svm_ptrs[i] is migrated.
1828+
///
1829+
/// \opencl_version_warning{2,1}
1830+
///
1831+
/// \see_opencl21_ref{clEnqueueSVMMigrateMem}
1832+
event enqueue_svm_migrate_memory(const std::vector<const void*> &svm_ptrs,
1833+
const std::vector<size_t> &sizes,
1834+
const cl_mem_migration_flags flags = 0,
1835+
const wait_list &events = wait_list())
1836+
{
1837+
BOOST_ASSERT(svm_ptrs.size() == sizes.size() || sizes.size() == 0);
1838+
event event_;
1839+
1840+
cl_int ret = clEnqueueSVMMigrateMem(
1841+
m_queue,
1842+
static_cast<cl_uint>(svm_ptrs.size()),
1843+
const_cast<void const **>(&svm_ptrs[0]),
1844+
sizes.size() > 0 ? &sizes[0] : NULL,
1845+
flags,
1846+
events.size(),
1847+
events.get_event_ptr(),
1848+
&event_.get()
1849+
);
1850+
1851+
if(ret != CL_SUCCESS){
1852+
BOOST_THROW_EXCEPTION(opencl_error(ret));
1853+
}
1854+
1855+
return event_;
1856+
}
1857+
1858+
/// Enqueues a command to indicate which device a range of SVM allocation
1859+
/// should be associated with. The pair \p svm_ptr and \p size together define
1860+
/// the starting address and number of bytes in a range to be migrated.
1861+
///
1862+
/// If \p size is 0, then the entire allocation containing \p svm_ptr is
1863+
/// migrated. The default value for \p size is 0.
1864+
///
1865+
/// \opencl_version_warning{2,1}
1866+
///
1867+
/// \see_opencl21_ref{clEnqueueSVMMigrateMem}
1868+
event enqueue_svm_migrate_memory(const void* svm_ptr,
1869+
const size_t size = 0,
1870+
const cl_mem_migration_flags flags = 0,
1871+
const wait_list &events = wait_list())
1872+
{
1873+
event event_;
1874+
1875+
cl_int ret = clEnqueueSVMMigrateMem(
1876+
m_queue,
1877+
cl_uint(1),
1878+
&svm_ptr,
1879+
&size,
1880+
flags,
1881+
events.size(),
1882+
events.get_event_ptr(),
1883+
&event_.get()
1884+
);
1885+
1886+
if(ret != CL_SUCCESS){
1887+
BOOST_THROW_EXCEPTION(opencl_error(ret));
1888+
}
1889+
1890+
return event_;
1891+
}
1892+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
1893+
18131894
/// Returns \c true if the command queue is the same at \p other.
18141895
bool operator==(const command_queue &other) const
18151896
{

test/test_svm_ptr.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,4 +110,47 @@ BOOST_AUTO_TEST_CASE(sum_svm_kernel)
110110
}
111111
#endif // BOOST_COMPUTE_CL_VERSION_2_0
112112

113+
#ifdef BOOST_COMPUTE_CL_VERSION_2_1
114+
BOOST_AUTO_TEST_CASE(migrate)
115+
{
116+
REQUIRES_OPENCL_VERSION(2, 1);
117+
118+
compute::svm_ptr<cl_int> ptr =
119+
compute::svm_alloc<cl_int>(context, 8);
120+
121+
// Migrate to device
122+
std::vector<const void*> ptrs(1, ptr.get());
123+
std::vector<size_t> sizes(1, 8 * sizeof(cl_int));
124+
queue.enqueue_svm_migrate_memory(ptrs, sizes).wait();
125+
126+
// Set on device
127+
const char source[] = BOOST_COMPUTE_STRINGIZE_SOURCE(
128+
__kernel void foo(__global int *ptr)
129+
{
130+
for(int i = 0; i < 8; i++){
131+
ptr[i] = i;
132+
}
133+
}
134+
);
135+
compute::program program =
136+
compute::program::build_with_source(source, context, "-cl-std=CL2.0");
137+
compute::kernel foo_kernel = program.create_kernel("foo");
138+
foo_kernel.set_arg(0, ptr);
139+
queue.enqueue_task(foo_kernel).wait();
140+
141+
// Migrate to host
142+
queue.enqueue_svm_migrate_memory(
143+
ptr.get(), 0, boost::compute::command_queue::migrate_to_host
144+
).wait();
145+
146+
// Check
147+
CHECK_HOST_RANGE_EQUAL(
148+
cl_int, 8,
149+
static_cast<cl_int*>(ptr.get()),
150+
(0, 1, 2, 3, 4, 5, 6, 7)
151+
);
152+
compute::svm_free(context, ptr);
153+
}
154+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
155+
113156
BOOST_AUTO_TEST_SUITE_END()

0 commit comments

Comments
 (0)