Modernization of conversions test (#1719)

* Modernization of conversions test, preparation to handle cl_khr_fp16 extension

* Added missing virtual descructor

* Added corrections due to code review

* More separators removed

* Fixed clang format

* Added multiple corrections related to code review

* Corrected missing implicit test lost after modernization corrections

* Corrected single, selected test to limit number of unnecessary operations
This commit is contained in:
Marcin Hajder
2023-07-11 17:52:25 +02:00
committed by GitHub
parent 3a1388a2b4
commit 2686b9e2c1
5 changed files with 2627 additions and 3497 deletions

View File

@@ -1,6 +1,6 @@
//
// Copyright (c) 2017 The Khronos Group Inc.
//
// Copyright (c) 2023 The Khronos Group Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
@@ -16,8 +16,6 @@
#ifndef BASIC_TEST_CONVERSIONS_H
#define BASIC_TEST_CONVERSIONS_H
#include "harness/compat.h"
#if !defined(_WIN32)
#include <unistd.h>
#endif
@@ -33,22 +31,23 @@
#endif
#include "harness/mt19937.h"
#include "harness/testHarness.h"
#include "harness/typeWrappers.h"
typedef void (*Convert)( void *dest, void *src, size_t );
#include <memory>
#include <tuple>
#include <vector>
#define kVectorSizeCount 6
#define kMaxVectorSize 16
#include "conversions_data_info.h"
typedef enum
{
kUnsaturated = 0,
kSaturated,
#define kVectorSizeCount 6
#define kMaxVectorSize 16
#define kPageSize 4096
kSaturationModeCount
}SaturationMode;
#define BUFFER_SIZE (1024 * 1024)
#define EMBEDDED_REDUCTION_FACTOR 16
#define PERF_LOOP_COUNT 100
extern Convert gConversions[kTypeCount][kTypeCount]; // [dest format][source format]
extern Convert gSaturatedConversions[kTypeCount][kTypeCount]; // [dest format][source format]
extern const char *gTypeNames[ kTypeCount ];
extern const char *gRoundingModeNames[ kRoundingModeCount ]; // { "", "_rte", "_rtp", "_rtn", "_rtz" }
extern const char *gSaturationNames[ kSaturationModeCount ]; // { "", "_sat" }
@@ -68,5 +67,324 @@ extern InitDataFunc gInitFunctions[ kTypeCount ];
typedef int (*CheckResults)( void *out1, void *out2, void *allowZ, uint32_t count, int vectorSize );
extern CheckResults gCheckResults[ kTypeCount ];
#define kCallStyleCount (kVectorSizeCount + 1 /* for implicit scalar */)
extern MTdata gMTdata;
extern cl_command_queue gQueue;
extern cl_context gContext;
extern cl_mem gInBuffer;
extern cl_mem gOutBuffers[];
extern int gHasDouble;
extern int gTestDouble;
extern int gWimpyMode;
extern int gWimpyReductionFactor;
extern int gSkipTesting;
extern int gMinVectorSize;
extern int gMaxVectorSize;
extern int gForceFTZ;
extern int gTimeResults;
extern int gReportAverageTimes;
extern int gStartTestNumber;
extern int gEndTestNumber;
extern int gIsRTZ;
extern void *gIn;
extern void *gRef;
extern void *gAllowZ;
extern void *gOut[];
extern const char **argList;
extern int argCount;
extern const char *sizeNames[];
extern int vectorSizes[];
extern size_t gComputeDevices;
extern uint32_t gDeviceFrequency;
namespace conv_test {
cl_program MakeProgram(Type outType, Type inType, SaturationMode sat,
RoundingMode round, int vectorSize,
cl_kernel *outKernel);
int RunKernel(cl_kernel kernel, void *inBuf, void *outBuf, size_t blockCount);
int GetTestCase(const char *name, Type *outType, Type *inType,
SaturationMode *sat, RoundingMode *round);
cl_int InitData(cl_uint job_id, cl_uint thread_id, void *p);
cl_int PrepareReference(cl_uint job_id, cl_uint thread_id, void *p);
uint64_t GetTime(void);
void WriteInputBufferComplete(void *);
void *FlushToZero(void);
void UnFlushToZero(void *);
}
struct CalcRefValsBase
{
virtual ~CalcRefValsBase() = default;
virtual int check_result(void *, uint32_t, int) { return 0; }
// pointer back to the parent WriteInputBufferInfo struct
struct WriteInputBufferInfo *parent;
clKernelWrapper kernel; // the kernel for this vector size
clProgramWrapper program; // the program for this vector size
cl_uint vectorSize; // the vector size for this callback chain
void *p; // the pointer to mapped result data for this vector size
cl_int result;
};
template <typename InType, typename OutType>
struct CalcRefValsPat : CalcRefValsBase
{
int check_result(void *, uint32_t, int) override;
};
struct WriteInputBufferInfo
{
WriteInputBufferInfo()
: calcReferenceValues(nullptr), doneBarrier(nullptr), count(0),
outType(kuchar), inType(kuchar), barrierCount(0)
{}
volatile cl_event
calcReferenceValues; // user event which signals when main thread is
// done calculating reference values
volatile cl_event
doneBarrier; // user event which signals when worker threads are done
cl_uint count; // the number of elements in the array
Type outType; // the data type of the conversion result
Type inType; // the data type of the conversion input
volatile int barrierCount;
std::vector<std::unique_ptr<CalcRefValsBase>> calcInfo;
};
// Must be aligned with Type enums!
using TypeIter = std::tuple<cl_uchar, cl_char, cl_ushort, cl_short, cl_uint,
cl_int, cl_float, cl_double, cl_ulong, cl_long>;
// Helper test fixture for constructing OpenCL objects used in testing
// a variety of simple command-buffer enqueue scenarios.
struct ConversionsTest
{
virtual ~ConversionsTest() = default;
ConversionsTest(cl_device_id device, cl_context context,
cl_command_queue queue);
cl_int SetUp(int elements);
// Test body returning an OpenCL error code
cl_int Run();
template <typename InType, typename OutType>
int DoTest(Type outType, Type inType, SaturationMode sat,
RoundingMode round);
template <typename InType, typename OutType>
void TestTypesConversion(const Type &inType, const Type &outType, int &tn,
const int smvs);
protected:
cl_context context;
cl_device_id device;
cl_command_queue queue;
size_t num_elements;
TypeIter typeIterator;
};
struct CustomConversionsTest : ConversionsTest
{
CustomConversionsTest(cl_device_id device, cl_context context,
cl_command_queue queue)
: ConversionsTest(device, context, queue)
{}
cl_int Run();
};
template <class T>
int MakeAndRunTest(cl_device_id device, cl_context context,
cl_command_queue queue, int num_elements)
{
T test_fixture(device, context, queue);
cl_int error = test_fixture.SetUp(num_elements);
test_error_ret(error, "Error in test initialization", TEST_FAIL);
return test_fixture.Run();
}
struct TestType
{
template <typename T> bool testType(Type in)
{
switch (in)
{
default: return false;
case kuchar: return std::is_same<cl_uchar, T>::value;
case kchar: return std::is_same<cl_char, T>::value;
case kushort: return std::is_same<cl_ushort, T>::value;
case kshort: return std::is_same<cl_short, T>::value;
case kuint: return std::is_same<cl_uint, T>::value;
case kint: return std::is_same<cl_int, T>::value;
case kfloat: return std::is_same<cl_float, T>::value;
case kdouble: return std::is_same<cl_double, T>::value;
case kulong: return std::is_same<cl_ulong, T>::value;
case klong: return std::is_same<cl_long, T>::value;
}
}
};
// Helper structures to iterate over all tuple attributes of different types
struct IterOverTypes : public TestType
{
IterOverTypes(const TypeIter &typeIter, ConversionsTest &test)
: inType((Type)0), outType((Type)0), typeIter(typeIter), test(test),
testNumber(-1), startMinVectorSize(gMinVectorSize)
{}
void Run() { for_each_out_elem(typeIter); }
protected:
template <std::size_t Out = 0, typename OutType>
void iterate_out_type(const OutType &t)
{
for_each_in_elem<0, Out, OutType>(typeIter);
outType = (Type)(outType + 1);
inType = (Type)0;
}
template <std::size_t In, std::size_t Out, typename OutType,
typename InType>
void iterate_in_type(const InType &t)
{
if (!testType<InType>(inType)) vlog_error("Unexpected data type!\n");
if (!testType<OutType>(outType)) vlog_error("Unexpected data type!\n");
// run the conversions
test.TestTypesConversion<InType, OutType>(inType, outType, testNumber,
startMinVectorSize);
inType = (Type)(inType + 1);
}
template <std::size_t Out = 0, typename... Tp>
inline typename std::enable_if<Out == sizeof...(Tp), void>::type
for_each_out_elem(
const std::tuple<Tp...> &) // Unused arguments are given no names.
{}
template <std::size_t Out = 0, typename... Tp>
inline typename std::enable_if < Out<sizeof...(Tp), void>::type
for_each_out_elem(const std::tuple<Tp...> &t)
{
iterate_out_type<Out>(std::get<Out>(t));
for_each_out_elem<Out + 1, Tp...>(t);
}
template <std::size_t In = 0, std::size_t Out, typename OutType,
typename... Tp>
inline typename std::enable_if<In == sizeof...(Tp), void>::type
for_each_in_elem(
const std::tuple<Tp...> &) // Unused arguments are given no names.
{}
template <std::size_t In = 0, std::size_t Out, typename OutType,
typename... Tp>
inline typename std::enable_if < In<sizeof...(Tp), void>::type
for_each_in_elem(const std::tuple<Tp...> &t)
{
iterate_in_type<In, Out, OutType>(std::get<In>(t));
for_each_in_elem<In + 1, Out, OutType, Tp...>(t);
}
protected:
Type inType;
Type outType;
const TypeIter &typeIter;
ConversionsTest &test;
int testNumber;
int startMinVectorSize;
};
// Helper structures to select type 2 type conversion test case
struct IterOverSelectedTypes : public TestType
{
IterOverSelectedTypes(const TypeIter &typeIter, ConversionsTest &test,
const Type in, const Type out,
const RoundingMode round, const SaturationMode sat)
: inType(in), outType(out), rounding(round), saturation(sat),
typeIter(typeIter), test(test), testNumber(-1),
startMinVectorSize(gMinVectorSize)
{}
void Run() { for_each_out_elem(typeIter); }
protected:
template <std::size_t Out = 0, typename OutType>
void iterate_out_type(const OutType &t)
{
for_each_in_elem<0, Out, OutType>(typeIter);
}
template <std::size_t In, std::size_t Out, typename OutType,
typename InType>
void iterate_in_type(const InType &t)
{
if (testType<InType>(inType) && testType<OutType>(outType))
{
// run selected conversion
// testing of the result will happen afterwards
test.DoTest<InType, OutType>(outType, inType, saturation, rounding);
}
}
template <std::size_t Out = 0, typename... Tp>
inline typename std::enable_if<Out == sizeof...(Tp), void>::type
for_each_out_elem(const std::tuple<Tp...> &)
{}
template <std::size_t Out = 0, typename... Tp>
inline typename std::enable_if < Out<sizeof...(Tp), void>::type
for_each_out_elem(const std::tuple<Tp...> &t)
{
iterate_out_type<Out>(std::get<Out>(t));
for_each_out_elem<Out + 1, Tp...>(t);
}
template <std::size_t In = 0, std::size_t Out, typename OutType,
typename... Tp>
inline typename std::enable_if<In == sizeof...(Tp), void>::type
for_each_in_elem(const std::tuple<Tp...> &)
{}
template <std::size_t In = 0, std::size_t Out, typename OutType,
typename... Tp>
inline typename std::enable_if < In<sizeof...(Tp), void>::type
for_each_in_elem(const std::tuple<Tp...> &t)
{
iterate_in_type<In, Out, OutType>(std::get<In>(t));
for_each_in_elem<In + 1, Out, OutType, Tp...>(t);
}
protected:
Type inType;
Type outType;
RoundingMode rounding;
SaturationMode saturation;
const TypeIter &typeIter;
ConversionsTest &test;
int testNumber;
int startMinVectorSize;
};
#endif /* BASIC_TEST_CONVERSIONS_H */