Files
OpenCL-CTS/test_conformance/math_brute_force/mad_float.cpp
Sven van Haastregt 1e5b5c96e2 math_brute_force: Remove unnecessary gotos (#1605)
Simplify code by returning directly instead of using goto statements.

Although intended as an NFC commit, this changes the behaviour around
clFlush calls.  Before this commit, failure of the third clFlush call
would print "clFlush 3 failed" and return the clFlush error code.
This behaviour is inconsistent with the other clFlush calls in
math_brute_force, which are not fatal.  The lack of a `goto exit`
makes me suspect that this 3rd clFlush call was intended to be
non-fatal too.  As such, this commit makes all clFlush calls non-fatal
by returning `CL_SUCCESS` even when the third clFlush call fails.

Original patch by Marco Antognini.

Signed-off-by: Marco Antognini <marco.antognini@arm.com>
Signed-off-by: Sven van Haastregt <sven.vanhaastregt@arm.com>
2023-02-07 09:01:07 -08:00

234 lines
7.8 KiB
C++

//
// Copyright (c) 2017 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#include "common.h"
#include "function_list.h"
#include "test_functions.h"
#include "utility.h"
#include <cstring>
namespace {
int BuildKernel(const char *name, int vectorSize, cl_kernel *k, cl_program *p,
bool relaxedMode)
{
auto kernel_name = GetKernelName(vectorSize);
auto source = GetTernaryKernel(kernel_name, name, ParameterType::Float,
ParameterType::Float, ParameterType::Float,
ParameterType::Float, vectorSize);
std::array<const char *, 1> sources{ source.c_str() };
return MakeKernel(sources.data(), sources.size(), kernel_name.c_str(), k, p,
relaxedMode);
}
using Kernels = std::array<clKernelWrapper, VECTOR_SIZE_COUNT>;
struct BuildKernelInfo2
{
Kernels &kernels;
Programs &programs;
const char *nameInCode;
bool relaxedMode; // Whether to build with -cl-fast-relaxed-math.
};
cl_int BuildKernelFn(cl_uint job_id, cl_uint thread_id UNUSED, void *p)
{
BuildKernelInfo2 *info = (BuildKernelInfo2 *)p;
cl_uint vectorSize = gMinVectorSizeIndex + job_id;
return BuildKernel(info->nameInCode, vectorSize,
&(info->kernels[vectorSize]),
&(info->programs[vectorSize]), info->relaxedMode);
}
} // anonymous namespace
int TestFunc_mad_Float(const Func *f, MTdata d, bool relaxedMode)
{
int error;
logFunctionInfo(f->name, sizeof(cl_float), relaxedMode);
Programs programs;
Kernels kernels;
float maxError = 0.0f;
float maxErrorVal = 0.0f;
float maxErrorVal2 = 0.0f;
float maxErrorVal3 = 0.0f;
uint64_t step = getTestStep(sizeof(float), BUFFER_SIZE);
// Init the kernels
BuildKernelInfo2 build_info{ kernels, programs, f->nameInCode,
relaxedMode };
if ((error = ThreadPool_Do(BuildKernelFn,
gMaxVectorSizeIndex - gMinVectorSizeIndex,
&build_info)))
return error;
for (uint64_t i = 0; i < (1ULL << 32); i += step)
{
// Init input array
cl_uint *p = (cl_uint *)gIn;
cl_uint *p2 = (cl_uint *)gIn2;
cl_uint *p3 = (cl_uint *)gIn3;
for (size_t j = 0; j < BUFFER_SIZE / sizeof(float); j++)
{
p[j] = genrand_int32(d);
p2[j] = genrand_int32(d);
p3[j] = genrand_int32(d);
}
if ((error = clEnqueueWriteBuffer(gQueue, gInBuffer, CL_FALSE, 0,
BUFFER_SIZE, gIn, 0, NULL, NULL)))
{
vlog_error("\n*** Error %d in clEnqueueWriteBuffer ***\n", error);
return error;
}
if ((error = clEnqueueWriteBuffer(gQueue, gInBuffer2, CL_FALSE, 0,
BUFFER_SIZE, gIn2, 0, NULL, NULL)))
{
vlog_error("\n*** Error %d in clEnqueueWriteBuffer2 ***\n", error);
return error;
}
if ((error = clEnqueueWriteBuffer(gQueue, gInBuffer3, CL_FALSE, 0,
BUFFER_SIZE, gIn3, 0, NULL, NULL)))
{
vlog_error("\n*** Error %d in clEnqueueWriteBuffer3 ***\n", error);
return error;
}
// Write garbage into output arrays
for (auto j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++)
{
uint32_t pattern = 0xffffdead;
if (gHostFill)
{
memset_pattern4(gOut[j], &pattern, BUFFER_SIZE);
if ((error = clEnqueueWriteBuffer(gQueue, gOutBuffer[j],
CL_FALSE, 0, BUFFER_SIZE,
gOut[j], 0, NULL, NULL)))
{
vlog_error(
"\n*** Error %d in clEnqueueWriteBuffer2(%d) ***\n",
error, j);
return error;
}
}
else
{
if ((error = clEnqueueFillBuffer(gQueue, gOutBuffer[j],
&pattern, sizeof(pattern), 0,
BUFFER_SIZE, 0, NULL, NULL)))
{
vlog_error("Error: clEnqueueFillBuffer failed! err: %d\n",
error);
return error;
}
}
}
// Run the kernels
for (auto j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++)
{
size_t vectorSize = sizeof(cl_float) * sizeValues[j];
size_t localCount = (BUFFER_SIZE + vectorSize - 1)
/ vectorSize; // BUFFER_SIZE / vectorSize rounded up
if ((error = clSetKernelArg(kernels[j], 0, sizeof(gOutBuffer[j]),
&gOutBuffer[j])))
{
LogBuildError(programs[j]);
return error;
}
if ((error = clSetKernelArg(kernels[j], 1, sizeof(gInBuffer),
&gInBuffer)))
{
LogBuildError(programs[j]);
return error;
}
if ((error = clSetKernelArg(kernels[j], 2, sizeof(gInBuffer2),
&gInBuffer2)))
{
LogBuildError(programs[j]);
return error;
}
if ((error = clSetKernelArg(kernels[j], 3, sizeof(gInBuffer3),
&gInBuffer3)))
{
LogBuildError(programs[j]);
return error;
}
if ((error =
clEnqueueNDRangeKernel(gQueue, kernels[j], 1, NULL,
&localCount, NULL, 0, NULL, NULL)))
{
vlog_error("FAILED -- could not execute kernel\n");
return error;
}
}
// Get that moving
if ((error = clFlush(gQueue))) vlog("clFlush failed\n");
// Calculate the correctly rounded reference result
float *r = (float *)gOut_Ref;
float *s = (float *)gIn;
float *s2 = (float *)gIn2;
float *s3 = (float *)gIn3;
for (size_t j = 0; j < BUFFER_SIZE / sizeof(float); j++)
r[j] = (float)f->func.f_fff(s[j], s2[j], s3[j]);
// Read the data back
for (auto j = gMinVectorSizeIndex; j < gMaxVectorSizeIndex; j++)
{
if ((error =
clEnqueueReadBuffer(gQueue, gOutBuffer[j], CL_TRUE, 0,
BUFFER_SIZE, gOut[j], 0, NULL, NULL)))
{
vlog_error("ReadArray failed %d\n", error);
return error;
}
}
if (gSkipCorrectnessTesting) break;
// Verify data -- No verification possible.
// MAD is a random number generator.
if (0 == (i & 0x0fffffff))
{
vlog(".");
fflush(stdout);
}
}
if (!gSkipCorrectnessTesting)
{
if (gWimpyMode)
vlog("Wimp pass");
else
vlog("passed");
vlog("\t%8.2f @ {%a, %a, %a}", maxError, maxErrorVal, maxErrorVal2,
maxErrorVal3);
}
vlog("\n");
return CL_SUCCESS;
}