1818#include < transformer_engine/normalization.h>
1919#include < transformer_engine/transformer_engine.h>
2020#include " ../test_common.h"
21+ #include " test_normalization.h"
2122
2223using namespace transformer_engine ;
2324using namespace test ;
2425
2526namespace {
2627
27- enum NormType {
28- LayerNorm,
29- RMSNorm
30- };
31-
32- std::map<NormType, std::string> normToString = {
33- {NormType::LayerNorm, " LayerNorm" },
34- {NormType::RMSNorm, " RmsNorm" }
35- };
36-
37- template <typename InputType>
38- void compute_ref_stats (NormType norm_type,
39- const InputType *data, float *mu, float *rsigma,
40- const size_t N, const size_t H, const double epsilon){
41- using compute_t = float ;
42- compute_t current, m;
43- for (size_t i = 0 ; i < N; ++i) {
44- compute_t sum = 0 ;
45- for (size_t j = 0 ; j < H; ++j) {
46- sum += static_cast <compute_t >(data[i * H + j]);
47- }
48- if (norm_type == LayerNorm){
49- mu[i] = sum / H;
50- m = mu[i];
51- } else { m = 0 ;}
52-
53- compute_t sum_sq = 0 ;
54- for (size_t j = 0 ; j < H; ++j) {
55- current = static_cast <compute_t >(data[i * H + j]);
56- sum_sq += (current - m) * (current - m);
57- }
58- rsigma[i] = rsqrtf ((sum_sq / H) + epsilon);
59- }
60- }
61-
62- // For now, cudnn does static_cast<compute_t>(gamma + static_cast<input_t>(1.0))
63- // This will be changed in the future release
64- template <typename InputType>
65- inline auto compute_gamma (InputType gamma, const bool zero_centered_gamma, const bool use_cudnn){
66-
67- using compute_t = float ;
68- if constexpr (std::is_same_v<InputType, fp8e5m2> || std::is_same_v<InputType, fp8e4m3>){
69- compute_t g = static_cast <compute_t >(gamma);
70- if (zero_centered_gamma) {
71- g += static_cast <compute_t >(1 .f );
72- }
73- return g;
74- } else {
75- if (use_cudnn){
76- compute_t g = static_cast <compute_t >(0 .f );
77- InputType gi = gamma;
78- if (zero_centered_gamma) {
79- gi = gi + static_cast <InputType>(1 .f );
80- }
81- g = static_cast <compute_t >(gi);
82- return g;
83- } else {
84- compute_t g = static_cast <compute_t >(gamma);
85- if (zero_centered_gamma) {
86- g += static_cast <compute_t >(1 .f );
87- }
88- return g;
89- }
90- }
91- }
92-
93- template <typename InputType, typename OutputType>
94- void compute_ref_output (NormType norm_type,
95- const InputType *data, const InputType *gamma, const InputType *beta,
96- OutputType* output,
97- const float *mu, const float *rsigma,
98- const size_t N, const size_t H,
99- float *amax, float scale, const bool zero_centered_gamma, const bool use_cudnn) {
100- using compute_t = float ;
101- compute_t current_max = -1e100 ;
102- for (size_t i = 0 ; i < N; ++i) {
103- for (size_t j = 0 ; j < H; ++j) {
104- compute_t current = static_cast <compute_t >(data[i * H + j]);
105- compute_t g = compute_gamma (gamma[j], zero_centered_gamma, use_cudnn);
106-
107- compute_t tmp;
108- if (norm_type == LayerNorm) {
109- tmp = (current - mu[i]) * rsigma[i] * g + static_cast <compute_t >(beta[j]);
110- } else { // RMSNorm
111- tmp = current * rsigma[i] * g;
112- }
113-
114- output[i * H + j] = static_cast <OutputType>(tmp * scale);
115- current_max = fmaxf (current_max, fabsf (tmp));
116- }
117- }
118- *amax = current_max;
119- }
120-
121-
122- template <typename InputType, typename OutputType>
123- void compute_ref_backward (const NormType norm_type, const OutputType *output_grad, const InputType *data,
124- const float *mu, const float *rsigma,
125- const InputType *gamma,
126- InputType *data_grad,
127- InputType *gamma_grad, InputType *beta_grad,
128- const size_t N, const size_t H,
129- const bool zero_centered_gamma, const bool use_cudnn) {
130- using compute_t = float ;
131- std::vector<compute_t > dgamma (H, 0 .f );
132- std::vector<compute_t > dbeta (H, 0 .f );
133-
134- for (size_t i = 0 ; i < N; ++i) {
135- // Reductions
136- auto local_mu = (norm_type == LayerNorm) ? mu[i] : 0 .;
137- compute_t mdy = 0 , mdyy = 0 ;
138- for (size_t j = 0 ; j < H; ++j) {
139- const compute_t x = static_cast <compute_t >(data[i * H + j]);
140- const compute_t y = (x - local_mu) * rsigma[i];
141- compute_t g = compute_gamma (gamma[j], zero_centered_gamma, use_cudnn);
142- const compute_t dz = static_cast <compute_t >(output_grad[i * H + j]);
143- const compute_t dy = g * dz;
144- dgamma[j] += y * dz;
145- if (norm_type == LayerNorm) {
146- dbeta[j] += dz;
147- mdy += dy;
148- }
149- mdyy += dy * y;
150- }
151- mdy /= H;
152- mdyy /= H;
153-
154- // Input grads
155- for (size_t j = 0 ; j < H; ++j) {
156- const compute_t x = static_cast <compute_t >(data[i * H + j]);
157- const compute_t y = (x - local_mu) * rsigma[i];
158- compute_t g = compute_gamma (gamma[j], zero_centered_gamma, use_cudnn);
159- const compute_t dz = static_cast <compute_t >(output_grad[i * H + j]);
160- const compute_t dy = g * dz;
161- const compute_t dx = rsigma[i] * (dy - mdyy * y - mdy);
162- data_grad[i * H + j] = static_cast <InputType>(dx);
163- }
164- }
165-
166- // Weight grads
167- for (size_t j = 0 ; j < H; ++j) gamma_grad[j] = static_cast <InputType>(dgamma[j]);
168- if (norm_type == LayerNorm) for (size_t j = 0 ; j < H; ++j) beta_grad[j] = static_cast <InputType>(dbeta[j]);
169- }
170-
17128template <typename InputType, typename OutputType>
17229void performTest (const size_t N, const size_t H, const bool zero_centered_gamma,
173- NormType norm_type, bool use_cudnn) {
30+ NormType norm_type, bool use_cudnn, const bool cudnn_zero_centered_gamma_in_weight_dtype ) {
17431 if (sizeof (InputType) < sizeof (OutputType)) {
17532 GTEST_SKIP () << " LN kernel does not support OutputType > InputType" ;
17633 return ;
@@ -224,6 +81,12 @@ void performTest(const size_t N, const size_t H, const bool zero_centered_gamma,
22481 nvte_enable_cudnn_norm_bwd (true );
22582 }
22683
84+ if (cudnn_zero_centered_gamma_in_weight_dtype) {
85+ nvte_enable_cudnn_norm_zero_centered_gamma_in_weight_dtype (true );
86+ } else {
87+ nvte_enable_cudnn_norm_zero_centered_gamma_in_weight_dtype (false );
88+ }
89+
22790 // Forward kernel
22891 float epsilon = 1e-5 ;
22992 if (norm_type == LayerNorm){
@@ -271,6 +134,10 @@ void performTest(const size_t N, const size_t H, const bool zero_centered_gamma,
271134 nvte_enable_cudnn_norm_bwd (false );
272135 }
273136
137+ if (cudnn_zero_centered_gamma_in_weight_dtype) {
138+ nvte_enable_cudnn_norm_zero_centered_gamma_in_weight_dtype (false );
139+ }
140+
274141 // Reference implementations
275142 // use the GPU stats to tighten the tolerances
276143 mu.to_cpu ();
@@ -289,14 +156,16 @@ void performTest(const size_t N, const size_t H, const bool zero_centered_gamma,
289156 &ref_amax,
290157 ref_scale,
291158 zero_centered_gamma,
292- use_cudnn);
159+ use_cudnn,
160+ cudnn_zero_centered_gamma_in_weight_dtype);
293161 compute_ref_backward (norm_type, dz.rowwise_cpu_dptr <WeightType>(),
294162 input.rowwise_cpu_dptr <InputType>(),
295163 mu.rowwise_cpu_dptr <float >(), rsigma.rowwise_cpu_dptr <float >(),
296164 gamma.rowwise_cpu_dptr <WeightType>(),
297165 ref_dx.get (), ref_dgamma.get (), ref_dbeta.get (),
298166 N, H, zero_centered_gamma,
299- use_cudnn);
167+ use_cudnn,
168+ cudnn_zero_centered_gamma_in_weight_dtype);
300169
301170 cudaDeviceSynchronize ();
302171 auto err = cudaGetLastError ();
@@ -341,6 +210,7 @@ NormType,
341210transformer_engine::DType,
342211 transformer_engine::DType,
343212 std::pair<size_t , size_t >,
213+ bool ,
344214 bool >> {};
345215
346216TEST_P (NormTestSuite, TestNorm) {
@@ -353,10 +223,11 @@ TEST_P(NormTestSuite, TestNorm) {
353223 const DType output_type = std::get<3 >(GetParam ());
354224 const auto size = std::get<4 >(GetParam ());
355225 const bool zero_centered_gamma = std::get<5 >(GetParam ());
226+ const bool cudnn_zero_centered_gamm_in_weight_dtype = std::get<6 >(GetParam ());
356227
357228 TRANSFORMER_ENGINE_TYPE_SWITCH_ALL (input_type, InputType,
358229 TRANSFORMER_ENGINE_TYPE_SWITCH_ALL (output_type, OutputType,
359- performTest<InputType, OutputType>(size.first , size.second , zero_centered_gamma, norm_type, use_cudnn);
230+ performTest<InputType, OutputType>(size.first , size.second , zero_centered_gamma, norm_type, use_cudnn, cudnn_zero_centered_gamm_in_weight_dtype );
360231 );
361232 );
362233}
@@ -370,6 +241,7 @@ INSTANTIATE_TEST_SUITE_P(
370241 ::testing::Values(DType::kFloat32 , DType::kBFloat16 , DType::kFloat16 ),
371242 ::testing::Values(DType::kFloat32 , DType::kBFloat16 , DType::kFloat16 , DType::kFloat8E4M3 ),
372243 ::testing::ValuesIn(test_cases),
244+ ::testing::Values(false , true ),
373245 ::testing::Values(false , true )),
374246 [](const testing::TestParamInfo<NormTestSuite::ParamType>& info) {
375247 auto backend = std::get<0 >(info.param ) == false ? " Te" : " Cudnn" ;
@@ -380,6 +252,7 @@ INSTANTIATE_TEST_SUITE_P(
380252 test::typeName (std::get<3 >(info.param )) + " X" +
381253 std::to_string (std::get<4 >(info.param ).first ) + " X" +
382254 std::to_string (std::get<4 >(info.param ).second ) + " X" +
383- std::to_string (std::get<5 >(info.param ));
255+ std::to_string (std::get<5 >(info.param )) + " X" +
256+ std::to_string (std::get<6 >(info.param ));
384257 return name;
385258 });
0 commit comments