1 ///////////////////////////////////////////////////////////////////////////////
2 //  Copyright (c) 2016 Thomas Heller
3 //  Copyright (c) 2016 Hartmut Kaiser
4 //
5 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
6 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 ///////////////////////////////////////////////////////////////////////////////
8 
9 #ifndef HPX_COMPUTE_CUDA_TARGET_HPP
10 #define HPX_COMPUTE_CUDA_TARGET_HPP
11 
12 #include <hpx/config.hpp>
13 
14 #if defined(HPX_HAVE_CUDA)
15 #include <hpx/compute/cuda/get_targets.hpp>
16 #include <hpx/lcos/future.hpp>
17 #include <hpx/lcos/local/spinlock.hpp>
18 #include <hpx/runtime/find_here.hpp>
19 #include <hpx/runtime/runtime_fwd.hpp>
20 
21 #include <hpx/runtime/serialization/serialization_fwd.hpp>
22 
23 #include <cuda_runtime.h>
24 
25 #include <cstddef>
26 #include <mutex>
27 #include <string>
28 #include <utility>
29 #include <vector>
30 
31 #include <hpx/config/warnings_prefix.hpp>
32 
33 namespace hpx { namespace compute { namespace cuda
34 {
35     ///////////////////////////////////////////////////////////////////////////
36     struct target
37     {
38     public:
39         struct HPX_EXPORT native_handle_type
40         {
41             typedef hpx::lcos::local::spinlock mutex_type;
42 
43             HPX_HOST_DEVICE native_handle_type(int device = 0);
44 
45             HPX_HOST_DEVICE ~native_handle_type();
46 
47             HPX_HOST_DEVICE native_handle_type(
48                 native_handle_type const& rhs) noexcept;
49             HPX_HOST_DEVICE native_handle_type(
50                 native_handle_type && rhs) noexcept;
51 
52             HPX_HOST_DEVICE native_handle_type&
53             operator=(native_handle_type const& rhs) noexcept;
54             HPX_HOST_DEVICE native_handle_type&
55             operator=(native_handle_type && rhs) noexcept;
56 
57             HPX_HOST_DEVICE cudaStream_t get_stream() const;
58 
get_devicehpx::compute::cuda::target::native_handle_type59             HPX_HOST_DEVICE int get_device() const noexcept
60             {
61                 return device_;
62             }
63 
processing_unitshpx::compute::cuda::target::native_handle_type64             HPX_HOST_DEVICE std::size_t processing_units() const
65             {
66                 return processing_units_;
67             }
68 
processor_familyhpx::compute::cuda::target::native_handle_type69             HPX_HOST_DEVICE std::size_t processor_family() const
70             {
71                 return processor_family_;
72             }
73 
processor_namehpx::compute::cuda::target::native_handle_type74             HPX_HOST_DEVICE std::string processor_name() const
75             {
76                 return processor_name_;
77             }
78 
79             void reset() noexcept;
80 
81         private:
82             void init_processing_units();
83             friend struct target;
84 
85             mutable mutex_type mtx_;
86             int device_;
87             std::size_t processing_units_;
88             std::size_t processor_family_;
89             std::string processor_name_;
90             mutable cudaStream_t stream_;
91         };
92 
93         // Constructs default target
targethpx::compute::cuda::target94         HPX_HOST_DEVICE target()
95           : handle_()
96 #if !defined(HPX_COMPUTE_DEVICE_CODE)
97           , locality_(hpx::find_here())
98 #endif
99         {}
100 
101         // Constructs target from a given device ID
targethpx::compute::cuda::target102         explicit HPX_HOST_DEVICE target(int device)
103           : handle_(device)
104 #if !defined(HPX_COMPUTE_DEVICE_CODE)
105           , locality_(hpx::find_here())
106 #endif
107         {}
108 
targethpx::compute::cuda::target109         HPX_HOST_DEVICE target(hpx::id_type const& locality, int device)
110           : handle_(device)
111 #if !defined(HPX_COMPUTE_DEVICE_CODE)
112           , locality_(locality)
113 #endif
114         {}
115 
targethpx::compute::cuda::target116         HPX_HOST_DEVICE target(target const& rhs) noexcept
117           : handle_(rhs.handle_)
118 #if !defined(HPX_COMPUTE_DEVICE_CODE)
119           , locality_(rhs.locality_)
120 #endif
121         {}
122 
targethpx::compute::cuda::target123         HPX_HOST_DEVICE target(target && rhs) noexcept
124           : handle_(std::move(rhs.handle_))
125 #if !defined(HPX_COMPUTE_DEVICE_CODE)
126           , locality_(std::move(rhs.locality_))
127 #endif
128         {}
129 
operator =hpx::compute::cuda::target130         HPX_HOST_DEVICE target& operator=(target const& rhs) noexcept
131         {
132             if (&rhs != this)
133             {
134                 handle_ = rhs.handle_;
135 #if !defined(HPX_COMPUTE_DEVICE_CODE)
136                 locality_ = rhs.locality_;
137 #endif
138             }
139             return *this;
140         }
141 
operator =hpx::compute::cuda::target142         HPX_HOST_DEVICE target& operator=(target && rhs) noexcept
143         {
144             if (&rhs != this)
145             {
146                 handle_ = std::move(rhs.handle_);
147 #if !defined(HPX_COMPUTE_DEVICE_CODE)
148                 locality_ = std::move(rhs.locality_);
149 #endif
150             }
151             return *this;
152         }
153 
154         HPX_HOST_DEVICE
native_handlehpx::compute::cuda::target155         native_handle_type& native_handle() noexcept
156         {
157             return handle_;
158         }
159         HPX_HOST_DEVICE
native_handlehpx::compute::cuda::target160         native_handle_type const& native_handle() const noexcept
161         {
162             return handle_;
163         }
164 
165         HPX_HOST_DEVICE void synchronize() const;
166 
get_localityhpx::compute::cuda::target167         HPX_HOST_DEVICE hpx::id_type const& get_locality() const noexcept
168         {
169             return locality_;
170         }
171 
172         hpx::future<void> get_future() const;
173 
get_local_targetshpx::compute::cuda::target174         static std::vector<target> get_local_targets()
175         {
176             return cuda::get_local_targets();
177         }
178         static hpx::future<std::vector<target> >
get_targetshpx::compute::cuda::target179             get_targets(hpx::id_type const& locality)
180         {
181             return cuda::get_targets(locality);
182         }
183 
operator ==(target const & lhs,target const & rhs)184         friend bool operator==(target const& lhs, target const& rhs)
185         {
186             return lhs.handle_.get_device() == rhs.handle_.get_device() &&
187                 lhs.locality_ == rhs.locality_;
188         }
189 
190     private:
191 #if !defined(HPX_COMPUTE_DEVICE_CODE)
192         friend class hpx::serialization::access;
193 
194         void serialize(serialization::input_archive& ar, const unsigned int);
195         void serialize(serialization::output_archive& ar, const unsigned int);
196 #endif
197 
198         native_handle_type handle_;
199         hpx::id_type locality_;
200     };
201 
202     HPX_API_EXPORT target& get_default_target();
203 }}}
204 
205 #include <hpx/config/warnings_suffix.hpp>
206 
207 #endif
208 #endif
209