vector.txx 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. /**
  2. * \file vector.txx
  3. * \author Dhairya Malhotra, dhairya.malhotra@gmail.com
  4. * \date 2-11-2011
  5. * \brief This file contains implementation of the class Vector.
  6. */
  7. #include <cassert>
  8. #include <iostream>
  9. #include <iomanip>
  10. #include <device_wrapper.hpp>
  11. #include <mem_utils.hpp>
  12. #include <profile.hpp>
  13. namespace pvfmm{
  14. template <class T>
  15. std::ostream& operator<<(std::ostream& output, const Vector<T>& V){
  16. output<<std::fixed<<std::setprecision(4)<<std::setiosflags(std::ios::left);
  17. for(size_t i=0;i<V.Dim();i++)
  18. output<<std::setw(10)<<V[i]<<' ';
  19. output<<";\n";
  20. return output;
  21. }
  22. template <class T>
  23. Vector<T>::Vector(){
  24. dim=0;
  25. capacity=0;
  26. own_data=true;
  27. data_ptr=NULL;
  28. dev.dev_ptr=(uintptr_t)NULL;
  29. }
  30. template <class T>
  31. Vector<T>::Vector(size_t dim_, T* data_, bool own_data_){
  32. dim=dim_;
  33. capacity=dim;
  34. own_data=own_data_;
  35. if(own_data){
  36. if(dim>0){
  37. data_ptr=mem::aligned_malloc<T>(capacity);
  38. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  39. Profile::Add_MEM(capacity*sizeof(T));
  40. #endif
  41. if(data_!=NULL) mem::memcopy(data_ptr,data_,dim*sizeof(T));
  42. }else data_ptr=NULL;
  43. }else
  44. data_ptr=data_;
  45. dev.dev_ptr=(uintptr_t)NULL;
  46. }
  47. template <class T>
  48. Vector<T>::Vector(const Vector<T>& V){
  49. dim=V.dim;
  50. capacity=dim;
  51. own_data=true;
  52. if(dim>0){
  53. data_ptr=mem::aligned_malloc<T>(capacity);
  54. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  55. Profile::Add_MEM(capacity*sizeof(T));
  56. #endif
  57. mem::memcopy(data_ptr,V.data_ptr,dim*sizeof(T));
  58. }else
  59. data_ptr=NULL;
  60. dev.dev_ptr=(uintptr_t)NULL;
  61. }
  62. template <class T>
  63. Vector<T>::Vector(const std::vector<T>& V){
  64. dim=V.size();
  65. capacity=dim;
  66. own_data=true;
  67. if(dim>0){
  68. data_ptr=mem::aligned_malloc<T>(capacity);
  69. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  70. Profile::Add_MEM(capacity*sizeof(T));
  71. #endif
  72. mem::memcopy(data_ptr,&V[0],dim*sizeof(T));
  73. }else
  74. data_ptr=NULL;
  75. dev.dev_ptr=(uintptr_t)NULL;
  76. }
  77. template <class T>
  78. Vector<T>::~Vector(){
  79. FreeDevice(false);
  80. if(own_data){
  81. if(data_ptr!=NULL){
  82. mem::aligned_free(data_ptr);
  83. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  84. Profile::Add_MEM(-capacity*sizeof(T));
  85. #endif
  86. }
  87. }
  88. data_ptr=NULL;
  89. capacity=0;
  90. dim=0;
  91. }
  92. template <class T>
  93. void Vector<T>::Swap(Vector<T>& v1){
  94. size_t dim_=dim;
  95. size_t capacity_=capacity;
  96. T* data_ptr_=data_ptr;
  97. bool own_data_=own_data;
  98. Device dev_=dev;
  99. dim=v1.dim;
  100. capacity=v1.capacity;
  101. data_ptr=v1.data_ptr;
  102. own_data=v1.own_data;
  103. dev=v1.dev;
  104. v1.dim=dim_;
  105. v1.capacity=capacity_;
  106. v1.data_ptr=data_ptr_;
  107. v1.own_data=own_data_;
  108. v1.dev=dev_;
  109. }
  110. template <class T>
  111. void Vector<T>::ReInit(size_t dim_, T* data_, bool own_data_){
  112. Vector<T> tmp(dim_,data_,own_data_);
  113. this->Swap(tmp);
  114. }
  115. template <class T>
  116. typename Vector<T>::Device& Vector<T>::AllocDevice(bool copy){
  117. if(dev.dev_ptr==(uintptr_t)NULL && dim>0) // Allocate data on device.
  118. dev.dev_ptr=DeviceWrapper::alloc_device((char*)data_ptr, dim*sizeof(T));
  119. if(dev.dev_ptr!=(uintptr_t)NULL && copy) // Copy data to device
  120. DeviceWrapper::host2device((char*)data_ptr,(char*)data_ptr,dev.dev_ptr,dim*sizeof(T));
  121. dev.dim=dim;
  122. return dev;
  123. }
  124. template <class T>
  125. void Vector<T>::Device2Host(){
  126. if(dev.dev_ptr==(uintptr_t)NULL) return;
  127. DeviceWrapper::device2host((char*)data_ptr,dev.dev_ptr,(char*)data_ptr,dim*sizeof(T));
  128. }
  129. template <class T>
  130. void Vector<T>::FreeDevice(bool copy){
  131. if(dev.dev_ptr==(uintptr_t)NULL) return;
  132. if(copy) DeviceWrapper::device2host((char*)data_ptr,dev.dev_ptr,(char*)data_ptr,dim*sizeof(T));
  133. DeviceWrapper::free_device((char*)data_ptr,dev.dev_ptr);
  134. dev.dev_ptr=(uintptr_t)NULL;
  135. dev.dim=0;
  136. }
  137. template <class T>
  138. void Vector<T>::Write(const char* fname){
  139. FILE* f1=fopen(fname,"wb+");
  140. if(f1==NULL){
  141. std::cout<<"Unable to open file for writing:"<<fname<<'\n';
  142. return;
  143. }
  144. int dim_=dim;
  145. fwrite(&dim_,sizeof(int),2,f1);
  146. fwrite(data_ptr,sizeof(T),dim,f1);
  147. fclose(f1);
  148. }
  149. template <class T>
  150. inline size_t Vector<T>::Dim() const{
  151. return dim;
  152. }
  153. template <class T>
  154. inline size_t Vector<T>::Capacity() const{
  155. return capacity;
  156. }
  157. template <class T>
  158. void Vector<T>::Resize(size_t dim_,bool fit_size){
  159. ASSERT_WITH_MSG(own_data || capacity>=dim_, "Resizing array beyond capacity when own_data=false.");
  160. if(dim!=dim_) FreeDevice(false);
  161. if((capacity>dim_ && !fit_size) || capacity==dim_ || !own_data){
  162. dim=dim_;
  163. return;
  164. }
  165. {
  166. if(data_ptr!=NULL){
  167. mem::aligned_free(data_ptr); data_ptr=NULL;
  168. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  169. Profile::Add_MEM(-capacity*sizeof(T));
  170. #endif
  171. }
  172. capacity=dim_;
  173. if(capacity>0){
  174. data_ptr=mem::aligned_malloc<T>(capacity);
  175. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  176. Profile::Add_MEM(capacity*sizeof(T));
  177. #endif
  178. }
  179. }
  180. dim=dim_;
  181. }
  182. template <class T>
  183. void Vector<T>::SetZero(){
  184. if(dim>0)
  185. memset(data_ptr,0,dim*sizeof(T));
  186. }
  187. template <class T>
  188. Vector<T>& Vector<T>::operator=(const Vector<T>& V){
  189. ASSERT_WITH_MSG(own_data || capacity>=V.dim, "Resizing array beyond capacity when own_data=false.");
  190. if(this!=&V){
  191. FreeDevice(false);
  192. if(own_data && capacity<V.dim){
  193. if(data_ptr!=NULL){
  194. mem::aligned_free(data_ptr); data_ptr=NULL;
  195. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  196. Profile::Add_MEM(-capacity*sizeof(T));
  197. #endif
  198. }
  199. capacity=V.dim;
  200. if(capacity>0){
  201. data_ptr=mem::aligned_malloc<T>(capacity);
  202. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  203. Profile::Add_MEM(capacity*sizeof(T));
  204. #endif
  205. }
  206. }
  207. dim=V.dim;
  208. mem::memcopy(data_ptr,V.data_ptr,dim*sizeof(T));
  209. }
  210. return *this;
  211. }
  212. template <class T>
  213. Vector<T>& Vector<T>::operator=(const std::vector<T>& V){
  214. ASSERT_WITH_MSG(own_data || capacity>=V.size(), "Resizing array beyond capacity when own_data=false.");
  215. {
  216. FreeDevice(false);
  217. if(own_data && capacity<V.size()){
  218. if(data_ptr!=NULL){
  219. mem::aligned_free(data_ptr); data_ptr=NULL;
  220. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  221. Profile::Add_MEM(-capacity*sizeof(T));
  222. #endif
  223. }
  224. capacity=V.size();
  225. if(capacity>0){
  226. data_ptr=mem::aligned_malloc<T>(capacity);
  227. #if !defined(__MIC__) || !defined(__INTEL_OFFLOAD)
  228. Profile::Add_MEM(capacity*sizeof(T));
  229. #endif
  230. }
  231. }
  232. dim=V.size();
  233. mem::memcopy(data_ptr,&V[0],dim*sizeof(T));
  234. }
  235. return *this;
  236. }
  237. template <class T>
  238. inline T& Vector<T>::operator[](size_t j) const{
  239. assert(dim>0?j<dim:j==0); //TODO Change to (j<dim)
  240. return data_ptr[j];
  241. }
  242. }//end namespace