@@ -13,41 +13,23 @@ See the License for the specific language governing permissions and
1313limitations under the License. */
1414#pragma once
1515
16- #include " paddle/fluid/operators/elementwise/elementwise_op.h"
17- #include " paddle/fluid/operators/elementwise/elementwise_op_function.cu.h"
18- #include " paddle/fluid/operators/elementwise/elementwise_op_function.h"
19- #if defined(PADDLE_WITH_CUDA) || defined(PADDLE_WITH_HIP)
20- #ifdef __NVCC__
21- #include < cuda.h>
22- #include < cuda_fp16.h>
23- #include " cub/cub.cuh"
24- #endif
25- #ifdef __HIPCC__
26- #include < hip/hip_fp16.h>
27- #include < hip/hip_runtime.h>
28- #include < hipcub/hipcub.hpp>
29- namespace cub = hipcub;
30- #endif
31- #endif
32-
3316namespace paddle {
3417namespace operators {
3518
36- #ifdef PADDLE_WITH_CUDA
37- #ifdef __NVCC__
38-
3919enum ElementwiseType { kUnary = 1 , kBinary = 2 };
4020
4121template <typename T, int Size>
42- struct alignas (sizeof (T) * Size) AlignedVector {
22+ struct alignas (sizeof (T) * Size) CudaAlignedVector {
4323 T val[Size];
4424};
4525
4626template <typename T>
4727int GetVectorizedSizeImpl (const T *pointer) {
4828 uint64_t address = reinterpret_cast <uint64_t >(pointer);
49- constexpr int vec4 = std::alignment_of<AlignedVector<T, 4 >>::value; // NOLINT
50- constexpr int vec2 = std::alignment_of<AlignedVector<T, 2 >>::value; // NOLINT
29+ constexpr int vec4 =
30+ std::alignment_of<CudaAlignedVector<T, 4 >>::value; // NOLINT
31+ constexpr int vec2 =
32+ std::alignment_of<CudaAlignedVector<T, 2 >>::value; // NOLINT
5133 if (address % vec4 == 0 ) {
5234 return 4 ;
5335 } else if (address % vec2 == 0 ) {
@@ -57,19 +39,21 @@ int GetVectorizedSizeImpl(const T *pointer) {
5739}
5840
5941template <typename T>
60- int GetVectorizedSize (const std::vector<const T *> ins,
61- const std::vector<T *> outs) {
42+ int GetVectorizedSize (const std::vector<const framework::Tensor *> & ins,
43+ const std::vector<framework::Tensor *> & outs) {
6244 int vec_size = 4 ;
6345 for (auto iter = ins.begin (); iter != ins.end (); ++iter) {
64- vec_size = std::min<int >(vec_size, GetVectorizedSizeImpl (*iter));
46+ vec_size =
47+ std::min<int >(vec_size, GetVectorizedSizeImpl ((*iter)->data <T>()));
6548 }
6649 for (auto iter = outs.begin (); iter != outs.end (); ++iter) {
67- vec_size = std::min<int >(vec_size, GetVectorizedSizeImpl (*iter));
50+ vec_size =
51+ std::min<int >(vec_size, GetVectorizedSizeImpl ((*iter)->data <T>()));
6852 }
6953 return vec_size;
7054}
7155
72- template <ElementwiseType N , int VecSize, typename T>
56+ template <ElementwiseType ET , int VecSize, typename T>
7357struct ElementwiseDataWrapper {
7458 T *out;
7559 const T *in0;
@@ -78,20 +62,20 @@ struct ElementwiseDataWrapper {
7862 const T *in1 = nullptr )
7963 : out(out), in0(in0), in1(in1) {}
8064
81- using VecType = AlignedVector <T, VecSize>;
65+ using VecType = CudaAlignedVector <T, VecSize>;
8266
8367 inline __device__ void load_vector (VecType args[], int idx) {
8468 const VecType *x_vec = reinterpret_cast <const VecType *>(in0);
8569 args[0 ] = x_vec[idx];
86- if (N == ElementwiseType::kBinary ) {
70+ if (ET == ElementwiseType::kBinary ) {
8771 const VecType *y_vec = reinterpret_cast <const VecType *>(in1);
8872 args[1 ] = y_vec[idx];
8973 }
9074 }
9175
9276 inline __device__ void load_scalar (T args[], int idx) {
9377 args[0 ] = in0[idx];
94- if (N == ElementwiseType::kBinary ) {
78+ if (ET == ElementwiseType::kBinary ) {
9579 args[1 ] = in1[idx];
9680 }
9781 }
@@ -104,16 +88,17 @@ struct ElementwiseDataWrapper {
10488 inline __device__ void store_scalar (T res, int idx) { out[idx] = res; }
10589};
10690
107- template <ElementwiseType N, int VecSize, typename T, typename Functor>
108- __device__ void VectorizedKernelImpl (ElementwiseDataWrapper<N, VecSize, T> data,
109- int size, Functor func, int tid) {
110- using VecType = AlignedVector<T, VecSize>;
111- VecType ins_vec[N];
91+ template <ElementwiseType ET , int VecSize, typename T, typename Functor>
92+ __device__ void VectorizedKernelImpl (
93+ ElementwiseDataWrapper<ET , VecSize, T> data, int size, Functor func,
94+ int tid) {
95+ using VecType = CudaAlignedVector<T, VecSize>;
96+ VecType ins_vec[ET ];
11297 VecType out_vec;
113- T *ins_ptr[N ];
98+ T *ins_ptr[ET ];
11499 T *out_ptr;
115100#pragma unroll
116- for (int i = 0 ; i < N ; ++i) {
101+ for (int i = 0 ; i < ET ; ++i) {
117102 ins_ptr[i] = reinterpret_cast <T *>(&(ins_vec[i]));
118103 }
119104 out_ptr = reinterpret_cast <T *>(&out_vec);
@@ -124,9 +109,9 @@ __device__ void VectorizedKernelImpl(ElementwiseDataWrapper<N, VecSize, T> data,
124109// compute
125110#pragma unroll
126111 for (int i = 0 ; i < VecSize; ++i) {
127- T ins[N ];
112+ T ins[ET ];
128113#pragma unroll
129- for (int j = 0 ; j < N ; ++j) {
114+ for (int j = 0 ; j < ET ; ++j) {
130115 ins[j] = ins_ptr[j][i];
131116 }
132117 out_ptr[i] = func (ins);
@@ -136,10 +121,11 @@ __device__ void VectorizedKernelImpl(ElementwiseDataWrapper<N, VecSize, T> data,
136121 data.store_vector (out_vec, tid);
137122}
138123
139- template <ElementwiseType N, typename T, typename Functor>
140- __device__ void ScalarKernelImpl (ElementwiseDataWrapper<N, 1 , T> data, int size,
141- Functor func, int start, int remain) {
142- T ins[N];
124+ template <ElementwiseType ET , typename T, typename Functor>
125+ __device__ void ScalarKernelImpl (ElementwiseDataWrapper<ET , 1 , T> data,
126+ int size, Functor func, int start,
127+ int remain) {
128+ T ins[ET ];
143129 T out;
144130
145131 for (int i = 0 ; i < remain; ++i) {
@@ -153,72 +139,67 @@ __device__ void ScalarKernelImpl(ElementwiseDataWrapper<N, 1, T> data, int size,
153139 }
154140}
155141
156- template <ElementwiseType N , int VecSize, typename T, typename Functor>
142+ template <ElementwiseType ET , int VecSize, typename T, typename Functor>
157143__global__ void VectorizedKernel (const T *__restrict__ in0,
158144 const T *__restrict__ in1, T *out, int size,
159145 Functor func) {
160146 int tid = blockIdx.x * blockDim.x + threadIdx.x ;
161147 int remain = size - VecSize * tid;
162148 remain = remain > 0 ? remain : 0 ;
163149 if (remain >= VecSize) {
164- auto data = ElementwiseDataWrapper<N , VecSize, T>(out, in0, in1);
150+ auto data = ElementwiseDataWrapper<ET , VecSize, T>(out, in0, in1);
165151 VectorizedKernelImpl (data, size, func, tid);
166152 } else {
167- auto data = ElementwiseDataWrapper<N , 1 , T>(out, in0, in1);
153+ auto data = ElementwiseDataWrapper<ET , 1 , T>(out, in0, in1);
168154 ScalarKernelImpl (data, size, func, tid * VecSize, remain);
169155 }
170156}
171157
172- template <ElementwiseType N , typename T, typename Functor>
158+ template <ElementwiseType ET , typename T, typename Functor>
173159__global__ void ScalarKernel (const T *__restrict__ in0,
174160 const T *__restrict__ in1, T *out, int size,
175161 Functor func) {
176- auto data = ElementwiseDataWrapper<N , 1 , T>(out, in0, in1);
162+ auto data = ElementwiseDataWrapper<ET , 1 , T>(out, in0, in1);
177163 int tid = blockIdx.x * blockDim.x + threadIdx.x ;
178164 int remain = tid < size ? 1 : 0 ;
179165 ScalarKernelImpl (data, size, func, tid, remain);
180166}
181167
182- template <ElementwiseType N , typename T, typename Functor>
183- void LaunchElementwiseCudaKernel (const framework::ExecutionContext &ctx,
184- const std::vector< const T *> &ins ,
185- std::vector<T *> outs, int size ,
186- Functor func) {
168+ template <ElementwiseType ET , typename T, typename Functor>
169+ void LaunchElementwiseCudaKernel (
170+ const platform::CUDADeviceContext &ctx ,
171+ const std::vector<const framework::Tensor *> &ins ,
172+ std::vector<framework::Tensor *> *outs, Functor func) {
187173 // calculate the max vec_size for all ins and outs
188- int vec_size = GetVectorizedSize (ins, outs);
174+ auto size = ins[0 ]->numel ();
175+ int vec_size = GetVectorizedSize<T>(ins, *outs);
189176 int block_size = PADDLE_CUDA_THREAD_SIZE ;
190177 int grid_size =
191178 ((size + vec_size - 1 ) / vec_size + block_size - 1 ) / block_size;
192- const T *in0 = ins[0 ];
193- const T *in1 = nullptr ;
194- if (N == ElementwiseType::kBinary ) {
195- in1 = ins[1 ];
196- }
197- T *out = outs[0 ];
179+ const T *in0 = ins[0 ]->data <T>();
180+ const T *in1 = (ET == ElementwiseType::kBinary ) ? ins[1 ]->data <T>() : nullptr ;
181+ T *out = (*outs)[0 ]->data <T>();
198182 // cuda kernel
199- auto stream =
200- ctx.template device_context <platform::CUDADeviceContext>().stream ();
183+ auto stream = ctx.stream ();
201184 switch (vec_size) {
202185 case 4 :
203- VectorizedKernel<N , 4 ><<<grid_size, block_size, 0 , stream>>>(
186+ VectorizedKernel<ET , 4 ><<<grid_size, block_size, 0 , stream>>>(
204187 in0, in1, out, size, func);
205188 break ;
206189 case 2 :
207- VectorizedKernel<N , 2 ><<<grid_size, block_size, 0 , stream>>>(
190+ VectorizedKernel<ET , 2 ><<<grid_size, block_size, 0 , stream>>>(
208191 in0, in1, out, size, func);
209192 break ;
210193 case 1 :
211- ScalarKernel<N ><<<grid_size, block_size, 0 , stream>>>(in0, in1, out, size ,
212- func);
194+ ScalarKernel<ET ><<<grid_size, block_size, 0 , stream>>>(in0, in1, out,
195+ size, func);
213196 break ;
214197 default :
215- PADDLE_THROW (
216- platform::errors::Unimplemented ( " Unsupported vectorized size! " ));
198+ PADDLE_THROW (platform::errors::Unimplemented (
199+ " Unsupported vectorized size: %d ! " , vec_size ));
217200 break ;
218201 }
219202}
220203
221- #endif
222- #endif
223204} // namespace operators
224205} // namespace paddle
0 commit comments