Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00

668 lines
29 KiB
C++

/*******************************************************************************
*
* MIT License
*
* Copyright (C) 2021-2025 Advanced Micro Devices, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include <hiptensor/hiptensor.h>
#include <algorithm>
#include "common.hpp"
#include "data_types.hpp"
#include "hiptensor_options.hpp"
#include "logger.hpp"
#include "reduction/reduction_cpu_reference.hpp"
#include "reduction_test.hpp"
#include "util.hpp"
#include "utils.hpp"
namespace
{
template <typename T>
void printReductionTestInputOutput(std::ostream& stream,
hiptensor::ReductionResource* resource,
size_t elementsA,
size_t elementsC,
size_t elementsD)
{
stream << "Tensor A elements (" << elementsA << "):\n";
hiptensorPrintArrayElements<T>(stream, (T*)resource->hostA().get(), elementsA);
stream << std::endl;
stream << "Tensor C elements (" << elementsC << "):\n";
hiptensorPrintArrayElements<T>(stream, (T*)resource->hostC().get(), elementsC);
stream << std::endl;
stream << "Tensor D elements (" << elementsD << "):\n";
hiptensorPrintArrayElements<T>(stream, (T*)resource->hostD().get(), elementsD);
stream << std::endl;
stream << "Refenrence elements (" << elementsD << "):\n";
hiptensorPrintArrayElements<T>(stream, (T*)resource->hostReference().get(), elementsD);
stream << std::endl;
}
}
namespace hiptensor
{
/*static*/ bool ReductionTest::mHeaderPrinted = false;
/*static*/ std::stringstream ReductionTest::sAPILogBuff = std::stringstream();
static void logMessage(int32_t logLevel, const char* funcName /*=""*/, const char* msg /*=""*/)
{
ReductionTest::sAPILogBuff << msg;
}
ReductionTest::ReductionTest()
: Base()
{
reset();
// Handle our own outputs
hiptensor::test::silenceLogger();
hiptensorLoggerSetCallback(logMessage);
}
// Kernel run checks. Virtual as different Reduction kernels have different requirements
// True = run test
// False = skip test
bool ReductionTest::checkDevice(hiptensorDataType_t datatype,
hiptensorComputeDescriptor_t computeDataType) const
{
return !(((datatype == HIPTENSOR_R_16F || datatype == HIPTENSOR_R_16BF
|| computeDataType == HIPTENSOR_COMPUTE_DESC_16F
|| computeDataType == HIPTENSOR_COMPUTE_DESC_16BF)
&& !isF16Supported())
|| ((datatype == HIPTENSOR_R_32F || computeDataType == HIPTENSOR_COMPUTE_DESC_32F)
&& !isF32Supported())
|| ((datatype == HIPTENSOR_R_64F || computeDataType == HIPTENSOR_COMPUTE_DESC_64F)
&& !isF64Supported()));
}
bool ReductionTest::checkSizes() const
{
return true;
}
void ReductionTest::reset()
{
mRepeats = 1u;
mRunFlag = true;
mValidationResult = false;
mMaxRelativeError = 0.0;
mElapsedTimeMs = mTotalGFlops = mMeasuredTFlopsPerSec = mTotalGBytes = mGBytesPerSec = 0.0;
}
ReductionResource* ReductionTest::getResource() const
{
return DataStorage::instance().get();
}
std::ostream& ReductionTest::printHeader(std::ostream& stream /* = std::cout */) const
{
// clang-format off
return stream
<< "TypeIn, " // 1
<< "TypeCompute, " // 2
<< "OperatorA, " // 3
<< "OperatorC, " // 4
<< "OperatorReduce, " // 5
<< "LogLevel, " // 6
<< "Lengths, " // 7
<< "memoryLayout, " // 8
<< "ReOrder, " // 9
<< "Alpha, " // 10
<< "Beta, " // 11
<< "ElapsedMs, " // 12
<< "Problem Size(GFlops), " // 13
<< "TFlops/s, " // 14
<< "TotalGBytes, " // 15
<< "GBytes/s, " // 16
<< "Result" // 17
<< std::endl;
// clang-format on
}
std::ostream& ReductionTest::printKernel(std::ostream& stream) const
{
auto param = Base::GetParam();
auto testType = std::get<0>(param);
auto logLevel = std::get<1>(param);
auto lengths = std::get<2>(param);
auto outputDims = std::get<3>(param);
auto alpha = std::get<4>(param);
auto beta = std::get<5>(param);
auto op = std::get<6>(param);
auto aOp = op[0];
auto cOp = op[1];
auto reduceOp = op[2];
auto memoryLayout = std::get<7>(param);
// clang-format off
stream << hipTypeToString(testType[0]) << ", " //1
<< computeTypeToString(convertToComputeType(testType[1])) << ", " //2
<< opTypeToString(aOp) << ", " //3
<< opTypeToString(cOp) << ", " //4
<< opTypeToString(reduceOp) << ", " //5
<< logLevelToString(logLevel) << ", "; //6
printContainerInCsv(lengths, stream) << ", "; //7
stream << hipMemoryLayoutToString(memoryLayout) << ", "; //8
printContainerInCsv(outputDims, stream) << ", "; //9
stream << alpha << ", " //10
<< beta << ", "; //11
// clang-format on
if(!mRunFlag)
{
// clang-format off
stream << "n/a" << ", " //12
<< "n/a" << ", " //13
<< "n/a" << ", " //14
<< "n/a" << ", " //15
<< "n/a" << ", " //16
<< "SKIPPED" //17
<< std::endl;
// clang-format on
}
else
{
auto isPerformValidation = HiptensorOptions::instance()->performValidation();
auto result = isPerformValidation ? (mValidationResult ? "PASSED" : "FAILED") : "BENCH";
// clang-format off
stream << mElapsedTimeMs << ", " // 12
<< mTotalGFlops << ", " // 13
<< mMeasuredTFlopsPerSec << ", " // 14
<< mTotalGBytes << ", " // 15
<< mGBytesPerSec << ", " // 16
<< result // 17
<< std::endl;
// clang-format on
}
return stream;
}
void ReductionTest::SetUp()
{
// reset API log buffer
sAPILogBuff.str(std::string());
auto param = Base::GetParam();
auto dataTypes = std::get<0>(param);
auto logLevel = std::get<1>(param);
auto lengths = std::get<2>(param);
auto outputDims = std::get<3>(param);
auto alpha = std::get<4>(param);
auto beta = std::get<5>(param);
auto op = std::get<6>(param);
auto memoryLayout = std::get<7>(param);
auto aOp = op[0];
auto cOp = op[1];
auto reduceOp = op[2];
EXPECT_TRUE((lengths.size() > 0) && (lengths.size() <= 6));
EXPECT_TRUE((outputDims.size() >= 0) && (outputDims.size() <= 6));
EXPECT_TRUE((reduceOp == HIPTENSOR_OP_ADD) || (reduceOp == HIPTENSOR_OP_MUL)
|| (reduceOp == HIPTENSOR_OP_MAX) || (reduceOp == HIPTENSOR_OP_MIN));
EXPECT_EQ(dataTypes.size(), 2); // HIPTENSOR_R_16F or HIPTENSOR_R_32F
auto acDataType = dataTypes[0];
auto computeDataType = convertToComputeType(dataTypes[1]);
EXPECT_TRUE(
(acDataType == HIPTENSOR_R_16F && computeDataType == HIPTENSOR_COMPUTE_DESC_16F)
|| (acDataType == HIPTENSOR_R_16F && computeDataType == HIPTENSOR_COMPUTE_DESC_32F)
|| (acDataType == HIPTENSOR_R_16BF && computeDataType == HIPTENSOR_COMPUTE_DESC_16BF)
|| (acDataType == HIPTENSOR_R_16BF && computeDataType == HIPTENSOR_COMPUTE_DESC_32F)
|| (acDataType == HIPTENSOR_R_32F && computeDataType == HIPTENSOR_COMPUTE_DESC_32F)
|| (acDataType == HIPTENSOR_R_64F && computeDataType == HIPTENSOR_COMPUTE_DESC_64F));
mRunFlag &= checkDevice(acDataType, computeDataType);
mRunFlag &= lengths.size() >= outputDims.size();
if(!mRunFlag)
{
GTEST_SKIP();
}
else
{
std::vector<size_t> outputLengths;
for(auto dim : outputDims)
{
outputLengths.push_back(lengths[dim]);
}
getResource()->setupStorage(lengths, outputLengths, acDataType);
// set mPrintElements to true to print element
mPrintElements = false;
}
}
void ReductionTest::reportResults(std::ostream& stream,
hiptensorDataType_t dataType,
bool omitHeader,
bool omitSkipped,
bool omitFailed,
bool omitPassed) const
{
if(!omitHeader)
{
printHeader(stream);
}
// Conditionally print outputs
if((mRunFlag || !omitSkipped) && (mValidationResult || !omitFailed)
&& (!mValidationResult || !omitPassed))
{
printKernel(stream);
if(mPrintElements)
{
auto resource = getResource();
auto param = Base::GetParam();
auto dataTypes = std::get<0>(param);
auto logLevel = std::get<1>(param);
auto lengths = std::get<2>(param);
auto outputDims = std::get<3>(param);
auto alpha = std::get<4>(param);
auto beta = std::get<5>(param);
auto op = std::get<6>(param);
auto memoryLayout = std::get<7>(param);
auto aOp = op[0];
auto cOp = op[1];
auto reduceOp = op[2];
stream << "Input [type: " << dataTypes << ", lengths: " << lengths
<< ", memoryLayout: " << memoryLayout << ", outputDims: " << outputDims
<< ", alpha: " << alpha << ", beta: " << beta << ", opReduce: [" << aOp
<< ", " << cOp << ", " << reduceOp << "]\n";
size_t elementsA = resource->getCurrentInputElementCount();
size_t elementsC = resource->getCurrentOutputElementCount();
size_t elementsD = elementsC;
if(dataType == HIPTENSOR_R_16BF)
{
printReductionTestInputOutput<bfloat16_t>(
stream, resource, elementsA, elementsC, elementsD);
}
else if(dataType == HIPTENSOR_R_16F)
{
printReductionTestInputOutput<float16_t>(
stream, resource, elementsA, elementsC, elementsD);
}
else if(dataType == HIPTENSOR_R_32F)
{
printReductionTestInputOutput<float32_t>(
stream, resource, elementsA, elementsC, elementsD);
}
else if(dataType == HIPTENSOR_R_64F)
{
printReductionTestInputOutput<float64_t>(
stream, resource, elementsA, elementsC, elementsD);
}
}
}
}
void ReductionTest::RunKernel()
{
auto param = Base::GetParam();
auto dataTypes = std::get<0>(param);
auto logLevel = std::get<1>(param);
auto lengths = std::get<2>(param);
auto outputDims = std::get<3>(param);
auto alpha = std::get<4>(param);
auto beta = std::get<5>(param);
auto op = std::get<6>(param);
auto memoryLayout = std::get<7>(param);
auto aOp = op[0];
auto cOp = op[1];
auto reduceOp = op[2];
auto acDataType = dataTypes[0];
auto computeDataType = convertToComputeType(dataTypes[1]);
if(!mRunFlag)
{
GTEST_SKIP();
}
auto resource = getResource();
if(mRunFlag)
{
std::vector<int> modeA(lengths.size());
std::iota(modeA.begin(), modeA.end(), 'a');
std::vector<int> modeC(outputDims.cbegin(), outputDims.cend());
std::transform(modeC.cbegin(), modeC.cend(), modeC.begin(), [&modeA](auto dim) {
return modeA[dim];
});
std::vector<int> modeD(modeC);
int nmodeA = modeA.size();
int nmodeC = modeC.size();
int nmodeD = nmodeC;
std::vector<int64_t> extentA(lengths.cbegin(), lengths.cend());
std::vector<int64_t> extentCD(outputDims.cbegin(), outputDims.cend());
std::transform(extentCD.cbegin(),
extentCD.cend(),
extentCD.begin(),
[&lengths](auto dim) { return lengths[dim]; });
std::vector<int64_t> stridesA
= memoryLayout == HIPTENSOR_MEMORY_LAYOUT_DEFAULT
? std::vector<int64_t>{}
: hiptensor::stridesFromLengths(
extentA, memoryLayout == HIPTENSOR_MEMORY_LAYOUT_COLUMN_MAJOR);
std::vector<int64_t> stridesCD
= memoryLayout == HIPTENSOR_MEMORY_LAYOUT_DEFAULT
? std::vector<int64_t>{}
: hiptensor::stridesFromLengths(
extentCD, memoryLayout == HIPTENSOR_MEMORY_LAYOUT_COLUMN_MAJOR);
hiptensorStatus_t err;
hiptensorHandle_t handle;
CHECK_HIPTENSOR_ERROR(hiptensorCreate(&handle));
CHECK_HIPTENSOR_ERROR(hiptensorLoggerSetMask(
logLevel
& ~HIPTENSOR_LOG_LEVEL_PERF_TRACE)); // keep ERROR/API_TRACE diagnostics but strip
// PERF_TRACE so the CK backend does not run its
// internal cold/hot timed loop
hiptensorTensorDescriptor_t descA = nullptr;
CHECK_HIPTENSOR_ERROR(
hiptensorCreateTensorDescriptor(handle,
&descA,
nmodeA,
extentA.data(),
stridesA.empty() ? nullptr : stridesA.data(),
acDataType,
0));
hiptensorTensorDescriptor_t descC = nullptr;
CHECK_HIPTENSOR_ERROR(
hiptensorCreateTensorDescriptor(handle,
&descC,
nmodeC,
extentCD.data(),
stridesCD.empty() ? nullptr : stridesCD.data(),
acDataType,
0));
hiptensorTensorDescriptor_t descD = nullptr;
CHECK_HIPTENSOR_ERROR(
hiptensorCreateTensorDescriptor(handle,
&descD,
nmodeD,
extentCD.data(),
stridesCD.empty() ? nullptr : stridesCD.data(),
acDataType,
0));
hiptensorComputeDescriptor_t const descCompute = convertToComputeType(dataTypes[1]);
hiptensorOperationDescriptor_t desc;
CHECK_HIPTENSOR_ERROR(hiptensorCreateReduction(handle,
&desc,
descA,
modeA.data(),
aOp,
descC,
modeC.data(),
cOp,
descD,
modeD.data(),
reduceOp,
descCompute));
const hiptensorAlgo_t algo = HIPTENSOR_ALGO_DEFAULT;
hiptensorPlanPreference_t planPref;
CHECK_HIPTENSOR_ERROR(
hiptensorCreatePlanPreference(handle, &planPref, algo, HIPTENSOR_JIT_MODE_NONE));
/**************************
* Disable Plan Cache for tests
***************************/
const hiptensorCacheMode_t cacheMode = HIPTENSOR_CACHE_MODE_NONE;
CHECK_HIPTENSOR_ERROR(
hiptensorPlanPreferenceSetAttribute(handle,
planPref,
HIPTENSOR_PLAN_PREFERENCE_CACHE_MODE,
&cacheMode,
sizeof(hiptensorCacheMode_t)));
uint64_t worksize = 0;
const hiptensorWorksizePreference_t workspacePref = HIPTENSOR_WORKSPACE_DEFAULT;
CHECK_HIPTENSOR_ERROR(
hiptensorEstimateWorkspaceSize(handle, desc, planPref, workspacePref, &worksize));
resource->setupWorkspace(worksize);
hiptensorPlan_t plan;
CHECK_HIPTENSOR_ERROR(hiptensorCreatePlan(handle, &plan, desc, planPref, worksize));
void* work = resource->deviceWorkspace().get();
double alphaValue{};
double betaValue{};
writeVal(&alphaValue, computeDataType, {computeDataType, alpha});
writeVal(&betaValue, computeDataType, {computeDataType, beta});
auto& opts = HiptensorOptions::instance();
int coldRuns = opts->coldRuns();
int hotRuns = std::max(1, opts->hotRuns()); // guard hot_runs <= 0
// untimed warm-up: ramps clocks, primes plan/caches
for(int i = 0; i < coldRuns; ++i)
CHECK_HIPTENSOR_ERROR(hiptensorReduce(handle,
plan,
(const void*)&alphaValue,
resource->deviceA().get(),
(const void*)&betaValue,
resource->deviceC().get(),
resource->deviceD().get(),
work,
worksize,
0));
hipEvent_t startEvent, stopEvent;
CHECK_HIP_ERROR(hipEventCreate(&startEvent));
CHECK_HIP_ERROR(hipEventCreate(&stopEvent));
CHECK_HIP_ERROR(hipEventRecord(startEvent));
for(int i = 0; i < hotRuns; ++i) // timed: M clean launches
CHECK_HIPTENSOR_ERROR(hiptensorReduce(handle,
plan,
(const void*)&alphaValue,
resource->deviceA().get(),
(const void*)&betaValue,
resource->deviceC().get(),
resource->deviceD().get(),
work,
worksize,
0));
CHECK_HIP_ERROR(hipEventRecord(stopEvent));
CHECK_HIP_ERROR(hipEventSynchronize(stopEvent))
auto timeMs = 0.0f;
CHECK_HIP_ERROR(hipEventElapsedTime(&timeMs, startEvent, stopEvent));
size_t sizeA = std::accumulate(extentA.begin(),
extentA.end(),
hiptensorDataTypeSize(acDataType),
std::multiplies<size_t>());
size_t sizeCD = std::accumulate(extentCD.begin(),
extentCD.end(),
hiptensorDataTypeSize(acDataType),
std::multiplies<size_t>());
mElapsedTimeMs = float64_t(timeMs) / hotRuns;
mTotalGFlops = sizeA / hiptensorDataTypeSize(acDataType) * 1e-9;
mMeasuredTFlopsPerSec = mTotalGFlops / mElapsedTimeMs;
mTotalGBytes = sizeA + sizeCD;
mTotalGBytes += (betaValue != 0.0) ? sizeCD : 0;
mTotalGBytes /= 1e9;
mGBytesPerSec = mTotalGBytes / (mElapsedTimeMs * 1e-3);
CHECK_HIP_ERROR(hipEventDestroy(startEvent));
CHECK_HIP_ERROR(hipEventDestroy(stopEvent));
auto& testOptions = HiptensorOptions::instance();
if(testOptions->performValidation())
{
resource->copyOutputToHost();
CHECK_HIPTENSOR_ERROR(hiptensorReductionReference(&alphaValue,
resource->hostA().get(),
descA,
modeA.data(),
aOp,
&betaValue,
resource->hostC().get(),
descC,
modeC.data(),
cOp,
resource->hostReference().get(),
descD,
modeD.data(),
reduceOp,
computeDataType,
0 /* stream */));
resource->copyReferenceToDevice();
if(acDataType == HIPTENSOR_R_16F)
{
std::tie(mValidationResult, mMaxRelativeError)
= compareEqualLaunchKernel<float16_t>(
(float16_t*)resource->deviceD().get(),
(float16_t*)resource->deviceReference().get(),
resource->getCurrentOutputElementCount(),
computeDataType);
}
else if(acDataType == HIPTENSOR_R_16BF)
{
std::tie(mValidationResult, mMaxRelativeError)
= compareEqualLaunchKernel<bfloat16_t>(
(bfloat16_t*)resource->deviceD().get(),
(bfloat16_t*)resource->deviceReference().get(),
resource->getCurrentOutputElementCount(),
computeDataType);
}
else if(acDataType == HIPTENSOR_R_32F)
{
auto reducedSize = resource->getCurrentInputElementCount()
/ resource->getCurrentOutputElementCount();
double tolerance = reducedSize * getEpsilon(computeDataType);
std::tie(mValidationResult, mMaxRelativeError)
= compareEqualLaunchKernel<float32_t>(
(float32_t*)resource->deviceD().get(),
(float32_t*)resource->deviceReference().get(),
resource->getCurrentOutputElementCount(),
computeDataType,
tolerance);
}
else if(acDataType == HIPTENSOR_R_64F)
{
auto reducedSize = resource->getCurrentInputElementCount()
/ resource->getCurrentOutputElementCount();
double tolerance = reducedSize * getEpsilon(computeDataType);
std::tie(mValidationResult, mMaxRelativeError)
= compareEqualLaunchKernel<float64_t>(
(float64_t*)resource->deviceD().get(),
(float64_t*)resource->deviceReference().get(),
resource->getCurrentOutputElementCount(),
computeDataType,
tolerance);
}
EXPECT_TRUE(mValidationResult) << "Max relative error: " << mMaxRelativeError;
} // if (testOptions->performValidation())
using Options = hiptensor::HiptensorOptions;
auto& loggingOptions = Options::instance();
if(!loggingOptions->omitCout())
{
std::cout << ReductionTest::sAPILogBuff.str();
reportResults(std::cout,
acDataType,
mHeaderPrinted,
loggingOptions->omitSkipped(),
loggingOptions->omitFailed(),
loggingOptions->omitPassed());
}
if(loggingOptions->logOstream().isOpen())
{
loggingOptions->logOstream().fstream() << ReductionTest::sAPILogBuff.str();
}
if(loggingOptions->ostream().isOpen())
{
reportResults(loggingOptions->ostream().fstream(),
acDataType,
mHeaderPrinted,
loggingOptions->omitSkipped(),
loggingOptions->omitFailed(),
loggingOptions->omitPassed());
}
// Print the header only once
if(!mHeaderPrinted)
{
mHeaderPrinted = true;
}
CHECK_HIPTENSOR_ERROR(hiptensorDestroy(handle));
CHECK_HIPTENSOR_ERROR(hiptensorDestroyPlan(plan));
CHECK_HIPTENSOR_ERROR(hiptensorDestroyPlanPreference(planPref));
CHECK_HIPTENSOR_ERROR(hiptensorDestroyOperationDescriptor(desc));
if(descA)
{
CHECK_HIPTENSOR_ERROR(hiptensorDestroyTensorDescriptor(descA));
descA = nullptr;
}
if(descC)
{
CHECK_HIPTENSOR_ERROR(hiptensorDestroyTensorDescriptor(descC));
descC = nullptr;
}
if(descD)
{
CHECK_HIPTENSOR_ERROR(hiptensorDestroyTensorDescriptor(descD));
descD = nullptr;
}
}
}
void ReductionTest::TearDown() {}
} // namespace hiptensor