TransformerEngine
123 строки · 4.2 Кб
1/*************************************************************************
2* Copyright (c) 2022-2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3*
4* See LICENSE for license information.
5************************************************************************/
6
7#include <cmath>
8#include <cstring>
9#include <memory>
10#include <iomanip>
11#include <iostream>
12#include <random>
13#include <type_traits>
14
15#include <cuda_bf16.h>
16#include <cuda_runtime.h>
17#include <gtest/gtest.h>
18
19#include <transformer_engine/activation.h>
20#include "../test_common.h"
21
22using namespace transformer_engine;
23
24template <typename IT, typename OT, typename CT>
25void compute_ref_gelu_cast(const IT *input_h,
26OT *output_h,
27const CT scale,
28CT *amax_h,
29const size_t N,
30const size_t H) {
31CT amax = 0.;
32
33for (size_t i = 0; i < N; i++) {
34for (size_t j = 0; j < H; j++) {
35CT elt = CT(input_h[i * H + j]);
36elt = 0.5f * elt * (1.0f + tanhf(0.79788456F * elt *
37(1.0f + 0.044715f * elt * elt)));
38output_h[i * H + j] = OT(scale * elt);
39amax = std::abs(elt) > amax ? std::abs(elt) : amax;
40}
41}
42
43*amax_h = amax;
44}
45
46template <typename IType, typename OType>
47void performTestGelu(const size_t N, const size_t H) {
48using namespace test;
49
50DType itype = TypeInfo<IType>::dtype;
51DType otype = TypeInfo<OType>::dtype;
52
53Tensor input({ N, H }, itype);
54Tensor output({ N, H }, otype);
55
56fillUniform(&input);
57setRandomScale(&output);
58
59std::unique_ptr<OType[]> ref_output = std::make_unique<OType[]>(N*H);
60
61nvte_gelu(input.data(), output.data(), 0);
62
63float ref_amax;
64compute_ref_gelu_cast(input.cpu_dptr<IType>(), ref_output.get(),
65output.scale(), &ref_amax, N, H);
66
67cudaDeviceSynchronize();
68auto err = cudaGetLastError();
69ASSERT_EQ(err, cudaSuccess) << cudaGetErrorString(err);
70
71if (otype == DType::kFloat8E4M3 || otype == DType::kFloat8E5M2) {
72auto [atol_amax, rtol_amax] = getTolerances(DType::kFloat32);
73compareResults("amax", output.amax(), ref_amax, atol_amax, rtol_amax);
74}
75auto [atol, rtol] = getTolerances(otype);
76compareResults("output_gelu", output, ref_output.get(), atol, rtol);
77}
78
79class GELUTestSuite : public ::testing::TestWithParam<std::tuple<transformer_engine::DType,
80transformer_engine::DType,
81std::pair<size_t, size_t>>> {};
82
83TEST_P(GELUTestSuite, TestGELU) {
84using namespace transformer_engine;
85using namespace test;
86
87const DType input_type = std::get<0>(GetParam());
88const DType output_type = std::get<1>(GetParam());
89const auto size = std::get<2>(GetParam());
90
91TRANSFORMER_ENGINE_TYPE_SWITCH_ALL(input_type, InputType,
92TRANSFORMER_ENGINE_TYPE_SWITCH_ALL(output_type, OutputType,
93performTestGelu<InputType, OutputType>(size.first, size.second);
94);
95);
96}
97
98namespace {
99
100std::vector<std::pair<size_t, size_t>> gelu_test_cases = {{2048, 12288},
101{768, 1024},
102{256, 65536},
103{65536, 128},
104{256, 256},
105{257, 259},
106{128, 128+1}};
107
108} // namespace
109
110INSTANTIATE_TEST_SUITE_P(
111OperatorTest,
112GELUTestSuite,
113::testing::Combine(
114::testing::Values(DType::kFloat32, DType::kBFloat16, DType::kFloat16),
115::testing::ValuesIn(test::all_fp_types),
116::testing::ValuesIn(gelu_test_cases)),
117[](const testing::TestParamInfo<GELUTestSuite::ParamType>& info) {
118std::string name = test::typeName(std::get<0>(info.param)) + "X" +
119test::typeName(std::get<1>(info.param)) + "X" +
120std::to_string(std::get<2>(info.param).first) + "X" +
121std::to_string(std::get<2>(info.param).second);
122return name;
123});
124