// Copyright Advanced Micro Devices, Inc., or its affiliates. // SPDX-License-Identifier: MIT #include #include #include #include #include #include using namespace TensileLite; using namespace TensileLite::Client; namespace { ContractionProblemGemm makePackedProblem(rocisa::DataType typeA, rocisa::DataType typeB, rocisa::DataType typeC, size_t M, size_t N, size_t K) { auto problem = ContractionProblemGemm::GEMM_Strides(false, false, typeA, typeB, typeC, typeC, M, N, K, 1, M, M * K, K, K * N, M, M * N, M, M * N, 0.0); problem.setComputeInputTypeA(typeA); problem.setComputeInputTypeB(typeB); problem.setAlphaType(typeC); problem.setBetaType(typeC); return problem; } } // namespace TEST(ReferenceFastPath, PreservesDoublePrecisionForF64) { const size_t M = 1; const size_t N = 1; const size_t K = 2; auto problem = makePackedProblem(rocisa::DataType::Double, rocisa::DataType::Double, rocisa::DataType::Double, M, N, K); ASSERT_TRUE(isFastPathEligible(problem)); const double a0 = 1.0 + std::ldexp(1.0, -40); const double a1 = 1.0 + std::ldexp(1.0, -41); const double b0 = 1.0 + std::ldexp(1.0, -42); const double b1 = 1.0 + std::ldexp(1.0, -43); std::vector a = {a0, a1}; std::vector b = {b0, b1}; std::vector c = {0.0}; std::vector d = {0.0}; ContractionInputs inputs(a.data(), b.data(), c.data(), d.data(), 1.0, 0.0); SolveGemmCPU(problem, inputs, /*elementsToValidate=*/-1, /*tryFastPath=*/true); const double expected = a0 * b0 + a1 * b1; ASSERT_NE(static_cast(static_cast(expected)), expected); EXPECT_EQ(d[0], expected); } TEST(ReferenceFastPath, AppliesXFloat32OperandMathOpToBothOperands) { const size_t M = 1; const size_t N = 1; const size_t K = 2; auto problem = makePackedProblem(rocisa::DataType::Float, rocisa::DataType::Float, rocisa::DataType::Float, M, N, K); problem.setF32XdlMathOp(rocisa::DataType::XFloat32); ASSERT_TRUE(isFastPathEligible(problem)); std::vector a = {1.234567f, -2.345678f}; std::vector b = {3.456789f, 4.567891f}; std::vector c = {0.0f}; std::vector d = {0.0f}; ContractionInputs inputs(a.data(), b.data(), c.data(), d.data(), 1.0f, 0.0f); SolveGemmCPU(problem, inputs, /*elementsToValidate=*/-1, /*tryFastPath=*/true); auto xf32 = [](float v) { return static_cast(XFloat32(v)); }; const float expected = xf32(a[0]) * xf32(b[0]) + xf32(a[1]) * xf32(b[1]); const float fullF32 = a[0] * b[0] + a[1] * b[1]; ASSERT_NE(expected, fullF32); EXPECT_EQ(d[0], expected); }