OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
cuda_kernel_error_checker.hpp
1 /*
2  * se_class1_cuda.hpp
3  *
4  * Created on: Jan 13, 2019
5  * Author: i-bird
6  */
7 
8 #ifndef SE_CLASS1_CUDA_HPP_
9 #define SE_CLASS1_CUDA_HPP_
10 
11 #include "util/se_util.hpp"
12 #include <type_traits>
13 #include <string>
14 
16 template<typename> struct Void_dev
17 {
19  typedef void type;
20 };
21 
22 template<typename T, typename Sfinae = void>
23 struct has_check_device_pointer: std::false_type {};
24 
33 template<typename T>
34 struct has_check_device_pointer<T, typename Void_dev< typename T::yes_has_check_device_pointer >::type> : std::true_type
35 {};
36 
38 {
40  bool match;
41 
43  std::string match_str;
44 };
45 
46 template<typename T, int type_of_t=has_check_device_pointer<T>::value>
47 struct check_type
48 {
49  static pointer_check check(void * ptr, int prp, T & arg)
50  {
51  pointer_check pc;
52 
53  pc.match = false;
54 
55  return pc;
56  }
57 };
58 
59 
60 
61 template<typename T>
62 struct check_type<T,1>
63 {
64  static pointer_check check(void * ptr, int prp, T & arg)
65  {
66  return arg.check_device_pointer(ptr);
67  }
68 };
69 
70 struct pos_pc
71 {
72  int pos;
73  pointer_check pc;
74 };
75 
76 template<typename ArgL>
77 pos_pc error_args_impl(void * ptr, int prp, ArgL argl)
78 {
79  pos_pc pp;
80  pointer_check pc = check_type<ArgL>::check(ptr,prp,argl);
81  if (pc.match == true)
82  {
83  pp.pos = 0;
84  pp.pc = pc;
85  return pp;
86  }
87 
88  pp.pos = -1;
89 
90  return pp;
91 }
92 
93 template<typename ArgL, typename ... Args>
94 pos_pc error_args_impl(void * ptr, int prp, ArgL argl, Args ... args)
95 {
96  pos_pc pp;
97  pointer_check pc = check_type<ArgL>::check(ptr,prp,argl);
98  if (pc.match == true)
99  {
100  pp.pos = sizeof...(args);
101  pp.pc = pc;
102  return pp;
103  }
104  return error_args_impl(ptr, prp, args ...);
105 }
106 
107 template<typename ... Args>pos_pc error_arg(void * ptr, int prp, Args ... args)
108 {
109  pos_pc pp;
110  pp = error_args_impl(ptr, prp, args ... );
111  pp.pos = sizeof...(args) - pp.pos - 1;
112  return pp;
113 }
114 
115 #include <boost/algorithm/string.hpp>
116 
117 #if defined(SE_CLASS1) && !defined(__clang__)
118 #define CUDA_LAUNCH_ERROR_OBJECT std::runtime_error("Runtime vector error");
119 #define CHECK_SE_CLASS1_PRE int dev_mem[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
120 
121 #if !defined(CUDA_ON_CPU)
122 
123  #define CHECK_SE_CLASS1_POST(kernel_call,...) \
124  cudaError_t e1 = cudaMemcpyFromSymbol(dev_mem,global_cuda_error_array,sizeof(dev_mem)); \
125  if (e1 != cudaSuccess)\
126  {\
127  std::string error = cudaGetErrorString(e1);\
128  std::cout << "Cuda Error in cudaMemcpyFromSymbol: " << __FILE__ << ":" << __LINE__ << " " << error << std::endl;\
129  }\
130  if (dev_mem[0] != 0)\
131  {\
132  void * ptr = (void *)*(size_t *)&dev_mem[1]; \
133  int prp_err = dev_mem[3];\
134  pos_pc ea = error_arg(ptr,prp_err,__VA_ARGS__);\
135  std::string args_s( #__VA_ARGS__ );\
136  std::vector<std::string> results;\
137  boost::split(results, args_s, [](char c){return c == ',';});\
138  std::string data_s;\
139  if (ea.pos >= results.size())\
140  {data_s = "Internal";}\
141  else\
142  {data_s = results[ea.pos];}\
143  std::cout << __FILE__ << ":" << __LINE__ << " Overflow detected in Kernel: " << kernel_call << " from the structure: " << data_s << " property: " << prp_err << " index:(" ;\
144  int i = 0; \
145  for ( ; i < dev_mem[4]-1 ; i++)\
146  {\
147  std::cout << dev_mem[5+i] << ",";\
148  }\
149  std::cout << dev_mem[5+i];\
150  std::cout << ")";\
151  std::cout << " thread: " << "(" << dev_mem[6+i] << "," << dev_mem[7+i] << "," << dev_mem[8+i] << ")*(" << dev_mem[9+i] << "," << dev_mem[10+i] << "," << dev_mem[11+i] << ")+(" << dev_mem[12+i] << "," << dev_mem[13+i] << "," << dev_mem[14+i] << ")" << std::endl;\
152  std::cout << "Internal error report: " << ea.pc.match_str << std::endl;\
153  int dev_mem_null[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\
154  cudaError_t e2 = cudaMemcpyToSymbol(global_cuda_error_array,dev_mem_null,sizeof(dev_mem_null),0,cudaMemcpyHostToDevice);\
155  if (e2 != cudaSuccess)\
156  {\
157  std::string error = cudaGetErrorString(e2);\
158  std::cout << "Cuda Error in cudaMemcpyToSymbol: " << __FILE__ << ":" << __LINE__ << " " << error << std::endl;\
159  }\
160  ACTION_ON_ERROR(CUDA_LAUNCH_ERROR_OBJECT);\
161  }\
162 
163 #else
164 
165  #define CHECK_SE_CLASS1_POST(kernel_call,...) \
166  memcpy(dev_mem,global_cuda_error_array,sizeof(dev_mem)); \
167  if (dev_mem[0] != 0)\
168  {\
169  void * ptr = (void *)*(size_t *)&dev_mem[1]; \
170  int prp_err = dev_mem[3];\
171  pos_pc ea = error_arg(ptr,prp_err,__VA_ARGS__);\
172  std::string args_s( #__VA_ARGS__ );\
173  std::vector<std::string> results;\
174  boost::split(results, args_s, [](char c){return c == ',';});\
175  std::string data_s;\
176  if (ea.pos >= results.size())\
177  {data_s = "Internal";}\
178  else\
179  {data_s = results[ea.pos];}\
180  std::cout << __FILE__ << ":" << __LINE__ << " Overflow detected in Kernel: " << kernel_call << " from the structure: " << data_s << " property: " << prp_err << " index:(" ;\
181  int i = 0; \
182  for ( ; i < dev_mem[4]-1 ; i++)\
183  {\
184  std::cout << dev_mem[5+i] << ",";\
185  }\
186  std::cout << dev_mem[5+i];\
187  std::cout << ")";\
188  std::cout << " thread: " << "(" << dev_mem[6+i] << "," << dev_mem[7+i] << "," << dev_mem[8+i] << ")*(" << dev_mem[9+i] << "," << dev_mem[10+i] << "," << dev_mem[11+i] << ")+(" << dev_mem[12+i] << "," << dev_mem[13+i] << "," << dev_mem[14+i] << ")" << std::endl;\
189  std::cout << "Internal error report: " << ea.pc.match_str << std::endl;\
190  int dev_mem_null[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\
191  memcpy(global_cuda_error_array,dev_mem_null,sizeof(dev_mem_null));\
192  ACTION_ON_ERROR(CUDA_LAUNCH_ERROR_OBJECT);\
193  }\
194 
195 #endif
196 
197 #else
198 #define CHECK_SE_CLASS1_PRE
199 #define CHECK_SE_CLASS1_POST(kernel_call,...)
200 #endif
201 
202 
203 #endif /* SE_CLASS1_CUDA_HPP_ */
bool match
Indicate if the pointer match.
void type
define void type
Void structure.
std::string match_str
match string