NVBIO
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
host_device_buffer.h
Go to the documentation of this file.
1 /*
2  * nvbio
3  * Copyright (c) 2011-2014, NVIDIA CORPORATION. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the NVIDIA CORPORATION nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #pragma once
29 
30 #include <thrust/host_vector.h>
31 #include <thrust/device_vector.h>
32 #include <nvbio/basic/types.h>
33 #include <nvbio/basic/vector.h>
34 #include <cuda_runtime.h>
35 
36 namespace nvbio {
37 namespace cuda {
38 
39 template <typename T>
41 {
42  virtual ~host_device_buffer() {}
43  virtual uint32 size() const { return 0u; }
44  virtual void resize(const uint32 size) {}
45  virtual void fill(const T val) {}
46  virtual void to_host() {}
47  virtual const T* host_ptr() const { return NULL; }
48  virtual const T* device_ptr() const { return NULL; }
49  virtual T* host_ptr() { return NULL; }
50  virtual T* device_ptr() { return NULL; }
51 };
52 
53 template <typename T>
55 {
59  {
60  // unmap the memory
61  cudaHostUnregister( host_ptr() );
62  }
63 
64  uint32 size() const { return m_hvec.size(); }
65 
66  void resize(const uint32 size)
67  {
68  // resize the vector
69  m_hvec.resize( size );
70 
71  // lock it and map it to the device
72  cudaError_t error = cudaHostRegister( &m_hvec[0], sizeof(T) * size, cudaHostRegisterMapped );
73  if (error)
74  {
75  log_error(stderr, "host_device_buffer_zero_copy::resize(): failed locking %llu bytes\n %s\n", sizeof(T)*size, cudaGetErrorString(error));
76  throw error;
77  }
78  }
79 
80  void fill(const T val)
81  {
82  thrust::fill( m_hvec.begin(), m_hvec.end(), val );
83  }
84 
85  void to_host() {}
86 
87  virtual const T* host_ptr() const { return thrust::raw_pointer_cast( &m_hvec.front() ); }
88  virtual const T* device_ptr() const
89  {
90  // get the mapped device pointer
91  T* ptr_d;
92  cudaError_t error = cudaHostGetDevicePointer( &ptr_d, const_cast<T*>(host_ptr()), 0u );
93  if (error)
94  {
95  log_error(stderr, "host_device_buffer_zero_copy::device_ptr(): failed mapping %llu bytes\n %s\n", sizeof(T)*m_hvec.size(), cudaGetErrorString(error));
96  throw error;
97  }
98  return ptr_d;
99  }
100  virtual T* host_ptr() { return thrust::raw_pointer_cast( &m_hvec.front() ); }
101  virtual T* device_ptr()
102  {
103  // get the mapped device pointer
104  T* ptr_d;
105  cudaError_t error = cudaHostGetDevicePointer( &ptr_d, host_ptr(), 0u );
106  if (error)
107  {
108  log_error(stderr, "host_device_buffer_zero_copy::device_ptr(): failed mapping %llu bytes\n %s\n", sizeof(T)*m_hvec.size(), cudaGetErrorString(error));
109  throw error;
110  }
111  return ptr_d;
112  }
113 
114 private:
115  thrust::host_vector<T> m_hvec;
116 };
117 
118 template <typename T>
120 {
124 
125  uint32 size() const { return m_hvec.size(); }
126 
127  void resize(const uint32 size)
128  {
129  m_hvec.resize( size );
130  m_dvec.resize( size );
131  }
132 
133  void fill(const T val)
134  {
135  thrust::fill( m_dvec.begin(), m_dvec.end(), val );
136  }
137 
138  void to_host()
139  {
140  thrust_copy_vector(m_hvec, m_dvec);
141  }
142 
143  virtual const T* host_ptr() const { return thrust::raw_pointer_cast( &m_hvec.front() ); }
144  virtual const T* device_ptr() const { return thrust::raw_pointer_cast( &m_dvec.front() ); }
145 
146  virtual T* host_ptr() { return thrust::raw_pointer_cast( &m_hvec.front() ); }
147  virtual T* device_ptr() { return thrust::raw_pointer_cast( &m_dvec.front() ); }
148 
149 private:
150  thrust::host_vector<T> m_hvec;
151  thrust::device_vector<T> m_dvec;
152 };
153 
154 template <typename T>
155 void copy(
156  const thrust::device_vector<T>& dvec,
157  thrust::host_vector<T>& hvec)
158 {
159  hvec = dvec;
160 }
161 
162 template <typename T>
163 void copy(
164  host_device_buffer<T>& dvec,
165  thrust::host_vector<T>& hvec)
166 {
167  dvec.to_host();
168  hvec.resize( dvec.size() );
169  thrust::copy(
170  dvec.host_ptr(),
171  dvec.host_ptr() + dvec.size(),
172  hvec.begin() );
173 }
174 
175 template <typename T>
176 const T* device_pointer(const thrust::device_vector<T>& dvec)
177 {
178  return thrust::raw_pointer_cast( &dvec.front() );
179 }
180 
181 template <typename T>
182 T* device_pointer(thrust::device_vector<T>& dvec)
183 {
184  return thrust::raw_pointer_cast( &dvec.front() );
185 }
186 
187 template <typename T>
189 {
190  return dvec.device_ptr();
191 }
192 
193 template <typename T>
195 {
196  return dvec.device_ptr();
197 }
198 
199 } // namespace cuda
200 } // namespace nvbio