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