HPXCL
/home/diehl/git/hpxcl/opencl/buffer.hpp
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
 All Classes Functions