HPXCL
|
00001 // Copyright (c) 2013 Martin Stumpf 00002 // 00003 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00005 00006 #pragma once 00007 #ifndef HPX_OPENCL_BUFFER_HPP_ 00008 #define HPX_OPENCL_BUFFER_HPP_ 00009 00010 // Default includes 00011 #include <hpx/hpx.hpp> 00012 #include <hpx/config.hpp> 00013 00014 // Export definitions 00015 #include "export_definitions.hpp" 00016 00017 // Forward Declarations 00018 #include "fwd_declarations.hpp" 00019 00020 // Crazy function overloading 00021 #include "util/enqueue_overloads.hpp" 00022 #include "util/rect_props.hpp" 00023 00024 #include "server/buffer.hpp" 00025 00026 namespace hpx { 00027 namespace opencl { 00028 00034 class HPX_OPENCL_EXPORT buffer 00035 : public hpx::components::client_base<buffer, server::buffer> 00036 { 00037 00038 typedef hpx::components::client_base<buffer, server::buffer> base_type; 00039 00040 public: 00041 // the result struct for enqueue_send 00042 struct send_result{ 00043 public: 00044 send_result( hpx::future<void>&& fut1, 00045 hpx::future<void>&& fut2 ) 00046 : src_future(std::move(fut1)), 00047 dst_future(std::move(fut2)){}; 00048 00049 hpx::future< void > src_future; 00050 hpx::future< void > dst_future; 00051 }; 00052 00053 00054 public: 00055 // Empty constructor, necessary for hpx purposes 00056 buffer(){} 00057 00058 // Constructor 00059 buffer(hpx::shared_future<hpx::naming::id_type> const& gid, 00060 hpx::naming::id_type device_gid_) 00061 : base_type(gid), device_gid(std::move(device_gid_)) 00062 { 00063 is_local = 00064 (hpx::get_colocation_id_sync(get_id()) == hpx::find_here()); 00065 } 00066 00067 // initialization 00068 00069 00070 // /////////////////////////////////////////////// 00071 // Exposed Component functionality 00072 // 00073 00079 hpx::future<std::size_t> 00080 size() const; 00081 00090 template<typename T, typename ...Deps> 00091 hpx::future<void> 00092 enqueue_write( std::size_t offset, 00093 const hpx::serialization::serialize_buffer<T> data, 00094 Deps &&... dependencies ); 00095 00105 template<typename T, typename ...Deps> 00106 hpx::future<void> 00107 enqueue_write_rect( 00108 rect_props rect_properties, 00109 const hpx::serialization::serialize_buffer<T> data, 00110 Deps &&... dependencies ); 00111 00121 template<typename ...Deps> 00122 hpx::future<hpx::serialization::serialize_buffer<char> > 00123 enqueue_read( std::size_t offset, 00124 std::size_t size, 00125 Deps &&... dependencies ); 00126 00141 template<typename T, typename ...Deps> 00142 hpx::future<hpx::serialization::serialize_buffer<T> > 00143 enqueue_read( std::size_t offset, 00144 hpx::serialization::serialize_buffer<T> data, 00145 Deps &&... dependencies ); 00146 00159 template<typename T, typename ...Deps> 00160 hpx::future<hpx::serialization::serialize_buffer<T> > 00161 enqueue_read_rect( rect_props rect_properties, 00162 hpx::serialization::serialize_buffer<T> data, 00163 Deps &&... dependencies ); 00164 00165 /* 00166 * @name Copies data to another buffer. 00167 * 00168 * The buffers do NOT need to be from the same device, 00169 * neither do they have to be on the same node. 00170 * 00171 * @param dst The source buffer. 00172 * @param src_offset The offset on the source buffer. 00173 * @param dst_offset The offset on the destination buffer. 00174 * @param size The size of the area to copy. 00175 * @return A future that can be used for synchronization 00176 * or dependency for other calls. 00177 * 00178 * @see event 00179 */ 00180 template<typename ...Deps> 00181 send_result enqueue_send( const hpx::opencl::buffer& dst, 00182 std::size_t src_offset, 00183 std::size_t dst_offset, 00184 std::size_t size, 00185 Deps &&... dependencies ); 00186 00187 /* 00188 * @name Copies data to another buffer. 00189 * 00190 * The buffers do NOT need to be from the same device, 00191 * neither do they have to be on the same node. 00192 * 00193 * @param dst The source buffer. 00194 * @param rect_properties Parameters of the rectangle to send. 00195 * @return A future that can be used for synchronization 00196 * or dependency for other calls. 00197 * 00198 * @see event 00199 */ 00200 template<typename ...Deps> 00201 send_result enqueue_send_rect( const hpx::opencl::buffer& dst, 00202 rect_props rect_properties, 00203 Deps &&... dependencies ); 00204 00205 00207 // Proxied functions 00208 // 00209 private: 00210 hpx::future<hpx::serialization::serialize_buffer<char> > 00211 enqueue_read_impl( std::size_t && offset, 00212 std::size_t && size, 00213 hpx::opencl::util::resolved_events && deps ); 00214 00215 send_result 00216 enqueue_send_impl( const hpx::opencl::buffer& dst, 00217 std::size_t && src_offset, 00218 std::size_t && dst_offset, 00219 std::size_t && size, 00220 hpx::opencl::util::resolved_events && deps ); 00221 00222 send_result 00223 enqueue_send_rect_impl( const hpx::opencl::buffer& dst, 00224 rect_props && rect_properties, 00225 hpx::opencl::util::resolved_events && deps ); 00226 private: 00227 hpx::naming::id_type device_gid; 00228 bool is_local; 00229 00230 private: 00231 // serialization support 00232 friend class hpx::serialization::access; 00233 00234 template <typename Archive> 00235 void load(Archive & ar, unsigned) 00236 { 00237 ar >> hpx::serialization::base_object<base_type>(*this); 00238 ar >> device_gid; 00239 is_local = 00240 (hpx::get_colocation_id_sync(get_id()) == hpx::find_here()); 00241 } 00242 00243 template <typename Archive> 00244 void save(Archive & ar, unsigned) const 00245 { 00246 ar << hpx::serialization::base_object<base_type>(*this); 00247 ar << device_gid; 00248 } 00249 00250 HPX_SERIALIZATION_SPLIT_MEMBER() 00251 00252 }; 00253 00254 }} 00255 00256 00258 // IMPLEMENTATIONS 00259 // 00260 template<typename T, typename ...Deps> 00261 hpx::future<hpx::serialization::serialize_buffer<T> > 00262 hpx::opencl::buffer::enqueue_read( std::size_t offset, 00263 hpx::serialization::serialize_buffer<T> data, 00264 Deps &&... dependencies ) 00265 { 00266 typedef hpx::serialization::serialize_buffer<T> buffer_type; 00267 00268 // combine dependency futures in one std::vector 00269 using hpx::opencl::util::enqueue_overloads::resolver; 00270 auto deps = resolver(std::forward<Deps>(dependencies)...); 00271 HPX_ASSERT(deps.are_from_device(device_gid)); 00272 00273 // create local event 00274 using hpx::opencl::lcos::event; 00275 event<buffer_type> ev( device_gid, data ); 00276 00277 // send command to server class 00278 typedef hpx::opencl::server::buffer 00279 ::enqueue_read_to_userbuffer_local_action<T> func_local; 00280 typedef hpx::opencl::server::buffer 00281 ::enqueue_read_to_userbuffer_remote_action<T> func_remote; 00282 if(!is_local){ 00283 // is remote call 00284 00285 hpx::apply<func_remote>( std::move(get_id()), 00286 std::move(ev.get_event_id()), 00287 offset, 00288 data.size() * sizeof(T), 00289 reinterpret_cast<std::uintptr_t> 00290 ( data.data() ), 00291 std::move(deps.event_ids) ); 00292 00293 } else { 00294 // is local call, send direct reference to buffer 00295 00296 hpx::apply<func_local>( std::move(get_id()), 00297 std::move(ev.get_event_id()), 00298 offset, 00299 data, 00300 std::move(deps.event_ids) ); 00301 } 00302 00303 // return future connected to event 00304 return ev.get_future(); 00305 } 00306 00307 template<typename T, typename ...Deps> 00308 hpx::future<hpx::serialization::serialize_buffer<T> > 00309 hpx::opencl::buffer::enqueue_read_rect( 00310 rect_props rect_properties, 00311 hpx::serialization::serialize_buffer<T> data, 00312 Deps &&... dependencies ) 00313 { 00314 typedef hpx::serialization::serialize_buffer<T> buffer_type; 00315 00316 // combine dependency futures in one std::vector 00317 using hpx::opencl::util::enqueue_overloads::resolver; 00318 auto deps = resolver(std::forward<Deps>(dependencies)...); 00319 HPX_ASSERT(deps.are_from_device(device_gid)); 00320 00321 // create local event 00322 using hpx::opencl::lcos::event; 00323 event<buffer_type> ev( device_gid, data ); 00324 00325 // send command to server class 00326 typedef hpx::opencl::server::buffer 00327 ::enqueue_read_to_userbuffer_rect_local_action<T> func_local; 00328 typedef hpx::opencl::server::buffer 00329 ::enqueue_read_to_userbuffer_rect_remote_action<T> func_remote; 00330 if(!is_local){ 00331 // is remote call 00332 00333 hpx::apply<func_remote>( std::move(get_id()), 00334 std::move(ev.get_event_id()), 00335 rect_properties, 00336 reinterpret_cast<std::uintptr_t> 00337 ( data.data() ), 00338 std::move(deps.event_ids) ); 00339 00340 } else { 00341 // is local call, send direct reference to buffer 00342 00343 hpx::apply<func_local>( std::move(get_id()), 00344 std::move(ev.get_event_id()), 00345 rect_properties, 00346 data, 00347 std::move(deps.event_ids) ); 00348 } 00349 00350 // return future connected to event 00351 return ev.get_future(); 00352 } 00353 00354 template<typename T, typename ...Deps> 00355 hpx::future<void> 00356 hpx::opencl::buffer::enqueue_write( std::size_t offset, 00357 const hpx::serialization::serialize_buffer<T> data, 00358 Deps &&... dependencies ) 00359 { 00360 // combine dependency futures in one std::vector 00361 using hpx::opencl::util::enqueue_overloads::resolver; 00362 auto deps = resolver(std::forward<Deps>(dependencies)...); 00363 HPX_ASSERT(deps.are_from_device(device_gid)); 00364 00365 // create local event 00366 using hpx::opencl::lcos::event; 00367 event<void> ev( device_gid ); 00368 00369 // send command to server class 00370 typedef hpx::opencl::server::buffer::enqueue_write_action<T> func; 00371 hpx::apply<func>( this->get_id(), 00372 ev.get_event_id(), 00373 offset, 00374 data, 00375 std::move(deps.event_ids) ); 00376 00377 00378 // return future connected to event 00379 return ev.get_future(); 00380 } 00381 00382 template<typename T, typename ...Deps> 00383 hpx::future<void> 00384 hpx::opencl::buffer::enqueue_write_rect( rect_props rect_properties, 00385 const hpx::serialization::serialize_buffer<T> data, 00386 Deps &&... dependencies ) 00387 { 00388 // combine dependency futures in one std::vector 00389 using hpx::opencl::util::enqueue_overloads::resolver; 00390 auto deps = resolver(std::forward<Deps>(dependencies)...); 00391 HPX_ASSERT(deps.are_from_device(device_gid)); 00392 00393 // create local event 00394 using hpx::opencl::lcos::event; 00395 event<void> ev( device_gid ); 00396 00397 // send command to server class 00398 typedef hpx::opencl::server::buffer::enqueue_write_rect_action<T> func; 00399 hpx::apply<func>( this->get_id(), 00400 ev.get_event_id(), 00401 rect_properties, 00402 data, 00403 std::move(deps.event_ids) ); 00404 00405 // return future connected to event 00406 return ev.get_future(); 00407 } 00408 00409 template<typename ...Deps> 00410 hpx::future<hpx::serialization::serialize_buffer<char> > 00411 hpx::opencl::buffer::enqueue_read( std::size_t offset, 00412 std::size_t size, 00413 Deps &&... dependencies ) 00414 { 00415 // combine dependency futures in one std::vector 00416 using hpx::opencl::util::enqueue_overloads::resolver; 00417 auto deps = resolver(std::forward<Deps>(dependencies)...); 00418 HPX_ASSERT(deps.are_from_device(device_gid)); 00419 00420 return enqueue_read_impl( std::move(offset), 00421 std::move(size), 00422 std::move(deps) ); 00423 } 00424 00425 template<typename ...Deps> 00426 hpx::opencl::buffer::send_result 00427 hpx::opencl::buffer::enqueue_send( const hpx::opencl::buffer& dst, 00428 std::size_t src_offset, 00429 std::size_t dst_offset, 00430 std::size_t size, 00431 Deps &&... dependencies ) 00432 { 00433 // combine dependency futures in one std::vector 00434 using hpx::opencl::util::enqueue_overloads::resolver; 00435 auto deps = resolver(std::forward<Deps>(dependencies)...); 00436 00437 return enqueue_send_impl( dst, 00438 std::move(src_offset), 00439 std::move(dst_offset), 00440 std::move(size), 00441 std::move(deps) ); 00442 } 00443 00444 template<typename ...Deps> 00445 hpx::opencl::buffer::send_result 00446 hpx::opencl::buffer::enqueue_send_rect( const hpx::opencl::buffer& dst, 00447 rect_props rect_properties, 00448 Deps &&... dependencies ) 00449 { 00450 // combine dependency futures in one std::vector 00451 using hpx::opencl::util::enqueue_overloads::resolver; 00452 auto deps = resolver(std::forward<Deps>(dependencies)...); 00453 00454 return enqueue_send_rect_impl( dst, 00455 std::move(rect_properties), 00456 std::move(deps) ); 00457 } 00458 00459 #endif