Skip to content

Commit cc958dc

Browse files
committed
math_brute_force: Refactor input generation & reduce default test size
This patch addresses execution time and input coverage in the math_brute_force tests by centralizing input generation and scaling down the default number of tested values. Key changes: * Abstracted input generation: Replaced duplicated array-filling logic across test files with shared `fill*Input` helper functions (for unary, binary, and ternary operations). This ensures that special edge-case values (NaNs, Infs, denormals) and random payloads are consistently injected across all tests. * Reduced default test size: The default loop bounds have been reduced from an exhaustive `1ULL << 32` values to a randomized subset of `1ULL << 27` inputs. This drastically speeds up standard test runs. * Added exhaustive `-a` flag: Introduced a new `-a` command-line option that restores the exhaustive testing behavior, allowing validation against all 2^32 sequential values when needed. * Improved wimpy mode scaling: Removed the `scale` and `step` skip logic, which could inadvertently skip combinations of special values. Instead, the patch now directly reduces the total `input_count_power_of_two` by using a De Bruijn sequence bit-hack to calculate the `log2` of the `wimpyReductionFactor`. Fixes: #2669
1 parent b559ccf commit cc958dc

43 files changed

Lines changed: 444 additions & 1201 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

test_conformance/math_brute_force/binary_double.cpp

Lines changed: 8 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ cl_int BuildKernelFn(cl_uint job_id, cl_uint thread_id UNUSED, void *p)
3838
}
3939

4040
// Thread specific data for a worker thread
41-
struct ThreadInfo
41+
struct ThreadInfo : public ThreadInfoBase
4242
{
4343
// Input and output buffers for the thread
4444
clMemWrapper inBuf;
@@ -50,10 +50,6 @@ struct ThreadInfo
5050
maxErrorValue; // position of the max error value (param 1). Init to 0.
5151
double maxErrorValue2; // position of the max error value (param 2). Init
5252
// to 0.
53-
MTdataHolder d;
54-
55-
// Per thread command queue to improve performance
56-
clCommandQueueWrapper tQueue;
5753
};
5854

5955
struct TestInfo : public TestInfoBase
@@ -74,7 +70,7 @@ cl_int Test(cl_uint job_id, cl_uint thread_id, void *data)
7470
TestInfo *job = (TestInfo *)data;
7571
size_t buffer_elements = job->subBufferSize;
7672
size_t buffer_size = buffer_elements * sizeof(cl_double);
77-
cl_uint base = job_id * (cl_uint)job->step;
73+
cl_uint base = job_id * (cl_uint)buffer_elements;
7874
ThreadInfo *tinfo = &(job->tinfo[thread_id]);
7975
float ulps = job->ulps;
8076
dptr func = job->f->dfunc;
@@ -118,42 +114,8 @@ cl_int Test(cl_uint job_id, cl_uint thread_id, void *data)
118114
// Init input array
119115
cl_ulong *p = (cl_ulong *)gIn + thread_id * buffer_elements;
120116
cl_ulong *p2 = (cl_ulong *)gIn2 + thread_id * buffer_elements;
121-
cl_uint idx = 0;
122-
123-
const std::vector<double> &specialValues = getDoubleSpecialValues();
124-
size_t specialValuesCount = specialValues.size();
125-
int totalSpecialValueCount = specialValuesCount * specialValuesCount;
126-
int lastSpecialJobIndex = (totalSpecialValueCount - 1) / buffer_elements;
127-
128-
// Test edge cases
129-
if (job_id <= (cl_uint)lastSpecialJobIndex)
130-
{
131-
cl_double *fp = (cl_double *)p;
132-
cl_double *fp2 = (cl_double *)p2;
133-
uint32_t x, y;
134-
135-
x = (job_id * buffer_elements) % specialValuesCount;
136-
y = (job_id * buffer_elements) / specialValuesCount;
137-
138-
for (; idx < buffer_elements; idx++)
139-
{
140-
fp[idx] = specialValues[x];
141-
fp2[idx] = specialValues[y];
142-
if (++x >= specialValuesCount)
143-
{
144-
x = 0;
145-
y++;
146-
if (y >= specialValuesCount) break;
147-
}
148-
}
149-
}
150-
151-
// Init any remaining values
152-
for (; idx < buffer_elements; idx++)
153-
{
154-
p[idx] = genrand_int64(d);
155-
p2[idx] = genrand_int64(d);
156-
}
117+
fillDoubleBinaryInput((cl_double *)p, (cl_double *)p2, buffer_elements,
118+
base, d);
157119

158120
if ((error = clEnqueueWriteBuffer(tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0,
159121
buffer_size, p, 0, NULL, NULL)))
@@ -433,10 +395,9 @@ cl_int Test(cl_uint job_id, cl_uint thread_id, void *data)
433395
{
434396
if (gVerboseBruteForce)
435397
{
436-
vlog("base:%14u step:%10u scale:%10u buf_elements:%10zu ulps:%5.3f "
398+
vlog("base:%14u buf_elements:%10zu ulps:%5.3f "
437399
"ThreadCount:%2u\n",
438-
base, job->step, job->scale, buffer_elements, job->ulps,
439-
job->threadCount);
400+
base, buffer_elements, job->ulps, job->threadCount);
440401
}
441402
else
442403
{
@@ -464,18 +425,8 @@ int TestFunc_Double_Double_Double(const Func *f, MTdata d, bool relaxedMode)
464425
test_info.threadCount = GetThreadCount();
465426
test_info.subBufferSize = BUFFER_SIZE
466427
/ (sizeof(cl_double) * RoundUpToNextPowerOfTwo(test_info.threadCount));
467-
test_info.scale = getTestScale(sizeof(cl_double));
468-
469-
test_info.step = (cl_uint)test_info.subBufferSize * test_info.scale;
470-
if (test_info.step / test_info.subBufferSize != test_info.scale)
471-
{
472-
// there was overflow
473-
test_info.jobCount = 1;
474-
}
475-
else
476-
{
477-
test_info.jobCount = (cl_uint)((1ULL << 32) / test_info.step);
478-
}
428+
test_info.jobCount = std::max(
429+
(cl_uint)1, (cl_uint)(getInputCount() / test_info.subBufferSize));
479430

480431
test_info.f = f;
481432
test_info.ulps = getAllowedUlpError(f, kdouble, relaxedMode);

test_conformance/math_brute_force/binary_float.cpp

Lines changed: 7 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ cl_int BuildKernelFn(cl_uint job_id, cl_uint thread_id UNUSED, void *p)
3838
}
3939

4040
// Thread specific data for a worker thread
41-
struct ThreadInfo
41+
struct ThreadInfo : public ThreadInfoBase
4242
{
4343
// Input and output buffers for the thread
4444
clMemWrapper inBuf;
@@ -50,10 +50,6 @@ struct ThreadInfo
5050
maxErrorValue; // position of the max error value (param 1). Init to 0.
5151
double maxErrorValue2; // position of the max error value (param 2). Init
5252
// to 0.
53-
MTdataHolder d;
54-
55-
// Per thread command queue to improve performance
56-
clCommandQueueWrapper tQueue;
5753
};
5854

5955
struct TestInfo : public TestInfoBase
@@ -74,7 +70,7 @@ cl_int Test(cl_uint job_id, cl_uint thread_id, void *data)
7470
TestInfo *job = (TestInfo *)data;
7571
size_t buffer_elements = job->subBufferSize;
7672
size_t buffer_size = buffer_elements * sizeof(cl_float);
77-
cl_uint base = job_id * (cl_uint)job->step;
73+
cl_uint base = job_id * (cl_uint)buffer_elements;
7874
ThreadInfo *tinfo = &(job->tinfo[thread_id]);
7975
fptr func = job->f->func;
8076
int ftz = job->ftz;
@@ -130,43 +126,7 @@ cl_int Test(cl_uint job_id, cl_uint thread_id, void *data)
130126
// Init input array
131127
cl_uint *p = (cl_uint *)gIn + thread_id * buffer_elements;
132128
cl_uint *p2 = (cl_uint *)gIn2 + thread_id * buffer_elements;
133-
cl_uint idx = 0;
134-
135-
const std::vector<float> &specialValues = getFloatSpecialValues();
136-
size_t specialValuesCount = specialValues.size();
137-
int totalSpecialValueCount = specialValuesCount * specialValuesCount;
138-
int lastSpecialJobIndex = (totalSpecialValueCount - 1) / buffer_elements;
139-
140-
// Test edge cases
141-
if (job_id <= (cl_uint)lastSpecialJobIndex)
142-
{
143-
float *fp = (float *)p;
144-
float *fp2 = (float *)p2;
145-
uint32_t x, y;
146-
147-
x = (job_id * buffer_elements) % specialValuesCount;
148-
y = (job_id * buffer_elements) / specialValuesCount;
149-
150-
for (; idx < buffer_elements; idx++)
151-
{
152-
fp[idx] = specialValues[x];
153-
fp2[idx] = specialValues[y];
154-
++x;
155-
if (x >= specialValuesCount)
156-
{
157-
x = 0;
158-
y++;
159-
if (y >= specialValuesCount) break;
160-
}
161-
}
162-
}
163-
164-
// Init any remaining values
165-
for (; idx < buffer_elements; idx++)
166-
{
167-
p[idx] = genrand_int32(d);
168-
p2[idx] = genrand_int32(d);
169-
}
129+
fillFloatBinaryInput((float *)p, (float *)p2, buffer_elements, base, d);
170130

171131
if ((error = clEnqueueWriteBuffer(tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0,
172132
buffer_size, p, 0, NULL, NULL)))
@@ -595,10 +555,9 @@ cl_int Test(cl_uint job_id, cl_uint thread_id, void *data)
595555
{
596556
if (gVerboseBruteForce)
597557
{
598-
vlog("base:%14u step:%10u scale:%10u buf_elements:%10zu ulps:%5.3f "
558+
vlog("base:%14u buf_elements:%10zu ulps:%5.3f "
599559
"ThreadCount:%2u\n",
600-
base, job->step, job->scale, buffer_elements, job->ulps,
601-
job->threadCount);
560+
base, buffer_elements, job->ulps, job->threadCount);
602561
}
603562
else
604563
{
@@ -626,18 +585,8 @@ int TestFunc_Float_Float_Float(const Func *f, MTdata d, bool relaxedMode)
626585
test_info.threadCount = GetThreadCount();
627586
test_info.subBufferSize = BUFFER_SIZE
628587
/ (sizeof(cl_float) * RoundUpToNextPowerOfTwo(test_info.threadCount));
629-
test_info.scale = getTestScale(sizeof(cl_float));
630-
631-
test_info.step = (cl_uint)test_info.subBufferSize * test_info.scale;
632-
if (test_info.step / test_info.subBufferSize != test_info.scale)
633-
{
634-
// there was overflow
635-
test_info.jobCount = 1;
636-
}
637-
else
638-
{
639-
test_info.jobCount = (cl_uint)((1ULL << 32) / test_info.step);
640-
}
588+
test_info.jobCount = std::max(
589+
(cl_uint)1, (cl_uint)(getInputCount() / test_info.subBufferSize));
641590

642591
test_info.f = f;
643592
test_info.ulps = gIsEmbedded ? f->float_embedded_ulps : f->float_ulps;

test_conformance/math_brute_force/binary_half.cpp

Lines changed: 7 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ cl_int BuildKernel_HalfFn(cl_uint job_id, cl_uint thread_id UNUSED, void *p)
4040
}
4141

4242
// Thread specific data for a worker thread
43-
struct ThreadInfo
43+
struct ThreadInfo : public ThreadInfoBase
4444
{
4545
clMemWrapper inBuf; // input buffer for the thread
4646
clMemWrapper inBuf2; // input buffer for the thread
@@ -50,10 +50,6 @@ struct ThreadInfo
5050
maxErrorValue; // position of the max error value (param 1). Init to 0.
5151
double maxErrorValue2; // position of the max error value (param 2). Init
5252
// to 0.
53-
MTdataHolder d;
54-
55-
clCommandQueueWrapper
56-
tQueue; // per thread command queue to improve performance
5753
};
5854

5955
struct TestInfo : public TestInfoBase
@@ -74,7 +70,7 @@ cl_int TestHalf(cl_uint job_id, cl_uint thread_id, void *data)
7470
TestInfo *job = (TestInfo *)data;
7571
size_t buffer_elements = job->subBufferSize;
7672
size_t buffer_size = buffer_elements * sizeof(cl_half);
77-
cl_uint base = job_id * (cl_uint)job->step;
73+
cl_uint base = job_id * (cl_uint)buffer_elements;
7874
ThreadInfo *tinfo = &(job->tinfo[thread_id]);
7975
float ulps = job->ulps;
8076
fptr func = job->f->func;
@@ -122,39 +118,7 @@ cl_int TestHalf(cl_uint job_id, cl_uint thread_id, void *data)
122118
cl_ushort *p = (cl_ushort *)gIn + thread_id * buffer_elements;
123119
cl_ushort *p2 = (cl_ushort *)gIn2 + thread_id * buffer_elements;
124120
j = 0;
125-
126-
const std::vector<cl_half> &specialValuesHalf = getHalfSpecialValues();
127-
size_t specialValuesHalfCount = specialValuesHalf.size();
128-
int totalSpecialValueCount =
129-
specialValuesHalfCount * specialValuesHalfCount;
130-
int indx = (totalSpecialValueCount - 1) / buffer_elements;
131-
132-
if (job_id <= (cl_uint)indx)
133-
{ // test edge cases
134-
uint32_t x, y;
135-
136-
x = (job_id * buffer_elements) % specialValuesHalfCount;
137-
y = (job_id * buffer_elements) / specialValuesHalfCount;
138-
139-
for (; j < buffer_elements; j++)
140-
{
141-
p[j] = specialValuesHalf[x];
142-
p2[j] = specialValuesHalf[y];
143-
if (++x >= specialValuesHalfCount)
144-
{
145-
x = 0;
146-
y++;
147-
if (y >= specialValuesHalfCount) break;
148-
}
149-
}
150-
}
151-
152-
// Init any remaining values.
153-
for (; j < buffer_elements; j++)
154-
{
155-
p[j] = (cl_ushort)genrand_int32(d);
156-
p2[j] = (cl_ushort)genrand_int32(d);
157-
}
121+
fillHalfBinaryInput((cl_half *)p, (cl_half *)p2, buffer_elements, base, d);
158122

159123
if ((error = clEnqueueWriteBuffer(tinfo->tQueue, tinfo->inBuf, CL_FALSE, 0,
160124
buffer_size, p, 0, NULL, NULL)))
@@ -582,10 +546,9 @@ cl_int TestHalf(cl_uint job_id, cl_uint thread_id, void *data)
582546
{
583547
if (gVerboseBruteForce)
584548
{
585-
vlog("base:%14u step:%10u scale:%10u buf_elements:%10zu ulps:%5.3f "
549+
vlog("base:%14u buf_elements:%10zu ulps:%5.3f "
586550
"ThreadCount:%2u\n",
587-
base, job->step, job->scale, buffer_elements, job->ulps,
588-
job->threadCount);
551+
base, buffer_elements, job->ulps, job->threadCount);
589552
}
590553
else
591554
{
@@ -614,18 +577,8 @@ int TestFunc_Half_Half_Half_common(const Func *f, MTdata d, int isNextafter,
614577
test_info.threadCount = GetThreadCount();
615578
test_info.subBufferSize = BUFFER_SIZE
616579
/ (sizeof(cl_half) * RoundUpToNextPowerOfTwo(test_info.threadCount));
617-
test_info.scale = getTestScale(sizeof(cl_half));
618-
619-
test_info.step = (cl_uint)test_info.subBufferSize * test_info.scale;
620-
if (test_info.step / test_info.subBufferSize != test_info.scale)
621-
{
622-
// there was overflow
623-
test_info.jobCount = 1;
624-
}
625-
else
626-
{
627-
test_info.jobCount = (cl_uint)((1ULL << 32) / test_info.step);
628-
}
580+
test_info.jobCount = std::max(
581+
(cl_uint)1, (cl_uint)(getInputCount() / test_info.subBufferSize));
629582

630583
test_info.f = f;
631584
test_info.ulps = getAllowedUlpError(f, khalf, relaxedMode);

0 commit comments

Comments
 (0)