Skip to content

Commit 251d02b

Browse files
authored
Merge pull request #731 from jszuppe/pr_svm_migrate_mem
Add wrapper for clEnqueueSVMMigrateMem()
2 parents 08e00e3 + f568c44 commit 251d02b

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)
@@ -1839,6 +1846,80 @@ class command_queue
18391846
}
18401847
#endif // BOOST_COMPUTE_CL_VERSION_2_0
18411848

1849+
#if defined(BOOST_COMPUTE_CL_VERSION_2_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
1850+
/// Enqueues a command to indicate which device a set of ranges of SVM allocations
1851+
/// should be associated with. The pair \p svm_ptrs[i] and \p sizes[i] together define
1852+
/// the starting address and number of bytes in a range to be migrated.
1853+
///
1854+
/// If \p sizes is empty, then that means every allocation containing any \p svm_ptrs[i]
1855+
/// is to be migrated. Also, if \p sizes[i] is zero, then the entire allocation containing
1856+
/// \p svm_ptrs[i] is migrated.
1857+
///
1858+
/// \opencl_version_warning{2,1}
1859+
///
1860+
/// \see_opencl21_ref{clEnqueueSVMMigrateMem}
1861+
event enqueue_svm_migrate_memory(const std::vector<const void*> &svm_ptrs,
1862+
const std::vector<size_t> &sizes,
1863+
const cl_mem_migration_flags flags = 0,
1864+
const wait_list &events = wait_list())
1865+
{
1866+
BOOST_ASSERT(svm_ptrs.size() == sizes.size() || sizes.size() == 0);
1867+
event event_;
1868+
1869+
cl_int ret = clEnqueueSVMMigrateMem(
1870+
m_queue,
1871+
static_cast<cl_uint>(svm_ptrs.size()),
1872+
const_cast<void const **>(&svm_ptrs[0]),
1873+
sizes.size() > 0 ? &sizes[0] : NULL,
1874+
flags,
1875+
events.size(),
1876+
events.get_event_ptr(),
1877+
&event_.get()
1878+
);
1879+
1880+
if(ret != CL_SUCCESS){
1881+
BOOST_THROW_EXCEPTION(opencl_error(ret));
1882+
}
1883+
1884+
return event_;
1885+
}
1886+
1887+
/// Enqueues a command to indicate which device a range of SVM allocation
1888+
/// should be associated with. The pair \p svm_ptr and \p size together define
1889+
/// the starting address and number of bytes in a range to be migrated.
1890+
///
1891+
/// If \p size is 0, then the entire allocation containing \p svm_ptr is
1892+
/// migrated. The default value for \p size is 0.
1893+
///
1894+
/// \opencl_version_warning{2,1}
1895+
///
1896+
/// \see_opencl21_ref{clEnqueueSVMMigrateMem}
1897+
event enqueue_svm_migrate_memory(const void* svm_ptr,
1898+
const size_t size = 0,
1899+
const cl_mem_migration_flags flags = 0,
1900+
const wait_list &events = wait_list())
1901+
{
1902+
event event_;
1903+
1904+
cl_int ret = clEnqueueSVMMigrateMem(
1905+
m_queue,
1906+
cl_uint(1),
1907+
&svm_ptr,
1908+
&size,
1909+
flags,
1910+
events.size(),
1911+
events.get_event_ptr(),
1912+
&event_.get()
1913+
);
1914+
1915+
if(ret != CL_SUCCESS){
1916+
BOOST_THROW_EXCEPTION(opencl_error(ret));
1917+
}
1918+
1919+
return event_;
1920+
}
1921+
#endif // BOOST_COMPUTE_CL_VERSION_2_1
1922+
18421923
/// Returns \c true if the command queue is the same at \p other.
18431924
bool operator==(const command_queue &other) const
18441925
{

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)