101 lines · plain
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file contains the definition of the HostRefChecker class, which11/// verifies the results of a device computation against a reference12/// implementation on the host.13///14//===----------------------------------------------------------------------===//15 16#ifndef MATHTEST_HOSTREFCHECKER_HPP17#define MATHTEST_HOSTREFCHECKER_HPP18 19#include "mathtest/Numerics.hpp"20#include "mathtest/Support.hpp"21#include "mathtest/TestResult.hpp"22 23#include "llvm/ADT/ArrayRef.h"24#include "llvm/ADT/Sequence.h"25#include "llvm/Support/Parallel.h"26 27#include <cstddef>28#include <tuple>29#include <utility>30 31namespace mathtest {32 33template <auto Func> class HostRefChecker {34 using FunctionTraits = FunctionTraits<Func>;35 using InTypesTuple = typename FunctionTraits::ArgTypesTuple;36 37 using FunctionConfig = FunctionConfig<Func>;38 39 template <typename... Ts>40 using BuffersTupleType = std::tuple<llvm::ArrayRef<Ts>...>;41 42public:43 using OutType = typename FunctionTraits::ReturnType;44 45private:46 template <typename... Ts>47 using PartialResultType = TestResult<OutType, Ts...>;48 49public:50 using ResultType = ApplyTupleTypes_t<InTypesTuple, PartialResultType>;51 using InBuffersTupleType = ApplyTupleTypes_t<InTypesTuple, BuffersTupleType>;52 53 HostRefChecker() = delete;54 55 static ResultType check(InBuffersTupleType InBuffersTuple,56 llvm::ArrayRef<OutType> OutBuffer) noexcept {57 const std::size_t BufferSize = OutBuffer.size();58 std::apply(59 [&](const auto &...InBuffers) {60 assert(61 ((InBuffers.size() == BufferSize) && ...) &&62 "All input buffers must have the same size as the output buffer");63 },64 InBuffersTuple);65 66 assert((BufferSize != 0) && "Buffer size cannot be zero");67 68 ResultType Init;69 70 auto Transform = [&](std::size_t Index) {71 auto CurrentInputsTuple = std::apply(72 [&](const auto &...InBuffers) {73 return std::make_tuple(InBuffers[Index]...);74 },75 InBuffersTuple);76 77 const OutType Actual = OutBuffer[Index];78 const OutType Expected = std::apply(Func, CurrentInputsTuple);79 80 const auto UlpDistance = computeUlpDistance(Actual, Expected);81 const bool IsFailure = UlpDistance > FunctionConfig::UlpTolerance;82 83 return ResultType(UlpDistance, IsFailure,84 typename ResultType::TestCase(85 std::move(CurrentInputsTuple), Actual, Expected));86 };87 88 auto Reduce = [](ResultType A, const ResultType &B) {89 A.accumulate(B);90 return A;91 };92 93 const auto Indexes = llvm::seq(BufferSize);94 return llvm::parallelTransformReduce(Indexes.begin(), Indexes.end(), Init,95 Reduce, Transform);96 }97};98} // namespace mathtest99 100#endif // MATHTEST_HOSTREFCHECKER_HPP101