Merge pull request #2 from tomatolib/feature/test-integration

Integrated tests
This commit is contained in:
gothictomato
2022-07-17 21:47:29 -04:00
committed by GitHub
5 changed files with 114 additions and 156 deletions

View File

@@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.22)
project(psat C)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_FLAGS "-O3")
# set(CMAKE_C_FLAGS "-O3")
add_executable(psat main.c cnf.c cnf.h time.c time.h types.h gpusolver.c gpusolver.h cpusolver.c cpusolver.h)
add_executable(psat main.c cnf.c cnf.h time.c time.h types.h gpusolver.c gpusolver.h cpusolver.c cpusolver.h tests/masterTest.c tests/masterTest.h)
target_link_libraries(psat -lOpenCL)

View File

@@ -2,146 +2,6 @@
#include <CL/cl.h>
#include "time.h"
static const char kernel_source[4560] = "static inline void stateaddpow(uint wcnt, uint* state, uint pow) {\n"
" uint corpow = pow & 0b11111U;\n"
" uint startind = pow >> 5U;\n"
" uint tr = 1U << corpow;\n"
" uint tval = state[startind] + tr;\n"
" uchar choice = !((tval > state[startind]) && (tval >= tr));\n"
" state[startind] = tval;\n"
" for (uint i = 0; i < wcnt; ++i) {\n"
" uchar cond = (i > startind);\n"
" state[i] += choice * cond;\n"
" choice = choice & (state[i] == 0) * cond + (!cond) & choice;\n"
" }\n"
"}\n"
"\n"
"__global static uint setmax;\n"
"\n"
"__kernel void vectorSAT(__global const uint* cnfheader, __global const uint* lvars, __global const uint* vars, __global const uint* clauses, __global const uchar* pars, __global uint* output, __global uchar* scratchpad, __global uint* maxvals) {\n"
" output[0] = 2;\n"
"\n"
" uint cnt = cnfheader[0];\n"
" uint vcnt = cnfheader[1];\n"
" uint ccnt = cnfheader[2];\n"
"\n"
" uint wcnt = 1 + (vcnt >> 5U);\n"
"\n"
" // Zero out the counter\n"
" for (uint i = 0; i < wcnt; ++i) output[i + 1] = 0;\n"
"\n"
" uint maxctr = 1U << (vcnt & 0b11111U);\n"
"\n"
" uint glbid = get_global_id(0);\n"
" uint glbsz = get_global_size(0);\n"
"\n"
" /*\n"
" uint locid = get_local_id(0);\n"
" uint locsz = get_local_size(0);\n"
" uint grpid = get_group_id(0);\n"
" uint grpcn = get_num_groups(0);\n"
" */\n"
"\n"
" bool done = false;\n"
" uint iter = 0;\n"
" while (output[0] == 2) {\n"
" // if (glbid == 0) printf(\"%s\\n\", \":~\");\n"
" setmax = 0;\n"
" uint maxnumx = 0;\n"
"\n"
" // Set all scratchpad clauses to true\n"
" for (uint j = 0; j < ccnt; j += glbsz) {\n"
" //uchar cond = (j + glbid) < ccnt;\n"
" // If ptr would go past end of array, set it to last element\n"
" // j = j * cond + (!cond) * (ccnt - glbid - 1);\n"
" if ((j + glbid) < ccnt) scratchpad[j + glbid] = 1;\n"
" }\n"
"\n"
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
"\n"
" for (uint j = 0; j < cnt; j += glbsz) {\n"
" // uchar cond = (j + glbid) < cnt;\n"
" // Last element cap\n"
" // j = j * cond + (!cond) * (cnt - glbid - 1);\n"
" if ((j + glbid) < cnt) {\n"
" uint varind = vars[j + glbid];\n"
" varind = (vcnt - 1) - varind;\n"
" uint iind = varind >> 5U;\n"
" uint bind = varind & 0b11111U;\n"
" uchar cpar = (output[iind + 1] >> bind) & 1U;\n"
" if (cpar != pars[j + glbid]) scratchpad[clauses[j + glbid]] = 0;\n"
" }\n"
" }\n"
"\n"
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
"\n"
"\n"
" for (uint j = 0; j < ccnt; j += glbsz) {\n"
" if (((j + glbid) < ccnt) && (scratchpad[j + glbid] == 1)) {\n"
" setmax = 1;\n"
" // printf(\"%u\\n\", (~output[1]) & 0b11111);\n"
" // printf(\"%u%u%u%u%u\\n\", (output[1] >> 4) & 1U, (output[1] >> 3) & 1U, (output[1] >> 2) & 1U, (output[1] >> 1) & 1U, output[1] & 1U);\n"
" // printf(\"%u - %u\\n\", j + glbid, scratchpad[j + glbid]);\n"
" }\n"
"\n"
" // uchar cond = (j + glbid) < cnt;\n"
" // Last element cap\n"
" // j = j * cond + (!cond) * (cnt - glbid - 1);\n"
" // if (scratchpad[j + glbid] == 1) setmax = true;\n"
" }\n"
"\n"
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
"\n"
" if (setmax) {\n"
" // Set maxval array to zero\n"
" maxvals[glbid] = 0;\n"
"\n"
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
"\n"
" // Accumulate and reduce the maximums\n"
" for (uint j = 0; j < ccnt; j += glbsz) {\n"
" uint a = maxvals[glbid];\n"
" uint b = scratchpad[j + glbid] * lvars[j + glbid];\n"
" uint c = max(a, b);\n"
" if ((j + glbid) < ccnt) maxvals[glbid] = c;\n"
" }\n"
"\n"
" barrier(CLK_GLOBAL_MEM_FENCE);\n"
"\n"
" // Final reduction pass\n"
" uint maxj = maxvals[0];\n"
" for (uint j = 1; j < glbsz; ++j) {\n"
" maxj = max(maxj, maxvals[j]);\n"
" }\n"
"\n"
" // Add to the counter\n"
" if (glbid == 0) {\n"
" // printf(\"> %u\\n\", maxj);\n"
" stateaddpow(wcnt, output + 1, maxj);\n"
" // printf(\">> %u%u%u%u%u\\n\", (output[1] >> 4) & 1U, (output[1] >> 3) & 1U, (output[1] >> 2) & 1U, (output[1] >> 1) & 1U, output[1] & 1U);\n"
" }\n"
"\n"
" // Check counter for overflow\n"
" if (output[wcnt] >= maxctr) {\n"
" output[0] = 1;\n"
" return;\n"
" }\n"
" } else {\n"
" // SAT. Set status and assignment.\n"
" output[0] = 0;\n"
" if (glbid == 0) {\n"
" for (uint i = 0; i < wcnt; ++i) output[i + 1] = ~output[i + 1];\n"
" }\n"
" return;\n"
" }\n"
" iter++;\n"
" }\n"
"}";
static const size_t kernel_len = 4559;
#define GLOBAL_SIZE (256)
#define LOCAL_SIZE (GLOBAL_SIZE)
@@ -181,13 +41,13 @@ i32 gpusolve(cnf* c) {
printf("Failed to retrieve OpenCL platform IDs\n");
exit(1);
}
printf("Found %u platforms\n", numplatforms);
// printf("Found %u platforms\n", numplatforms);
res = clGetDeviceIDs(platformid, CL_DEVICE_TYPE_GPU, 1, &deviceid, &numdevices);
if (res != CL_SUCCESS) {
printf("Failed to retrieve OpenCL device IDs\n");
exit(1);
}
printf("Found %u devices\n", numdevices);
// printf("Found %u devices\n", numdevices);
cl_context context = clCreateContext(NULL, 1, &deviceid, NULL, NULL, &res);
if (res != CL_SUCCESS) {
@@ -289,8 +149,6 @@ i32 gpusolve(cnf* c) {
exit(1);
}
const char* kernelptr = kernel_source;
cl_program satprog = clCreateProgramWithSource(context, 1, (const char**) &source_str, (const size_t*) &source_size, &res);
if (res != CL_SUCCESS) {
printf("Failed to create OpenCL program\n");
@@ -329,8 +187,7 @@ i32 gpusolve(cnf* c) {
res = clSetKernelArg(kernel, 6, sizeof(cl_mem), (void*) &gpuscratchpad);
res = clSetKernelArg(kernel, 7, LOCAL_SIZE * sizeof(cl_uint), NULL);
u64 starttime = utime();
// u64 starttime = utime();
size_t itemsize[2] = {GLOBAL_SIZE, LOCAL_SIZE };
res = clEnqueueNDRangeKernel(commqueue, kernel, 1, NULL, itemsize, itemsize + 1, 0, NULL, NULL);
if (res != CL_SUCCESS) {
@@ -338,14 +195,12 @@ i32 gpusolve(cnf* c) {
exit(res);
}
res = clEnqueueReadBuffer(commqueue, gpuoutput, CL_TRUE, 0, (wordcnt + 1) * sizeof(cl_uint), solution, 0, NULL, NULL);
if (res != CL_SUCCESS) {
printf("Failed to read kernel output\n");
exit(1);
}
u64 endtime = utime();
// u64 endtime = utime();
if (solution[0] == 1) {
printf("UNSAT\n");
@@ -370,7 +225,7 @@ i32 gpusolve(cnf* c) {
for (u32 i = 0; i < c->clausecnt; ++i) {
if (!assigncheck[i]) {
printf("Failed assignment check\n");
exit(1);
solution[0] = 4;
}
}
free(assigncheck);
@@ -378,14 +233,18 @@ i32 gpusolve(cnf* c) {
}
} else {
printf("What the fuck???\n");
exit(1);
solution[0] = 3;
}
printf("Actual time: %f seconds\n", ((f64) (endtime - starttime)) / 1000000.0);
// printf("Actual time: %f seconds\n", ((f64) (endtime - starttime)) / 1000000.0);
res = clFlush(commqueue);
res = clFinish(commqueue);
res = clReleaseKernel(kernel);
res = clReleaseProgram(satprog);
res = clReleaseCommandQueue(commqueue);
res = clReleaseContext(context);
res = clReleaseMemObject(gpuheader);
res = clReleaseMemObject(gpulvars);
res = clReleaseMemObject(gpuvariables);
@@ -393,8 +252,9 @@ i32 gpusolve(cnf* c) {
res = clReleaseMemObject(gpuparities);
res = clReleaseMemObject(gpuoutput);
res = clReleaseMemObject(gpuscratchpad);
res = clReleaseCommandQueue(commqueue);
res = clReleaseContext(context);
res = clReleaseDevice(deviceid);
i32 retval = solution[0];
free(solution);
free(source_str);

3
main.c
View File

@@ -2,6 +2,7 @@
#include "cnf.h"
#include "gpusolver.h"
#include "time.h"
#include "tests/masterTest.h"
int main() {
/*
@@ -25,6 +26,8 @@ int main() {
}
*/
/* Expects a path to a DIMACS file */
cnf* c = readDIMACS("/home/lev/Downloads/uf50/uf50-088.cnf");
// printf("%u\n", c->litcnt);

87
tests/masterTest.c Normal file
View File

@@ -0,0 +1,87 @@
#include "masterTest.h"
#include <stdio.h>
#include "../cnf.h"
#include "../gpusolver.h"
#include "../time.h"
i32 runTests() {
i32 res = runuf20();
if (res != 0) return res;
res = runuf50();
if (res != 0) return res;
res = runuuf50();
return res;
}
i32 runuf20() {
printf("Running against uf20\n");
u32 passed = 0;
u64 tottime = 0;
for (u32 i = 0; i < 1000; ++i) {
char buf[128];
i32 len = sprintf(buf, "/home/lev/Downloads/uf20/uf20-0%u.cnf", i + 1);
cnf* c = readDIMACS(buf);
sortlastnum(c, c->litcnt);
u64 start = utime();
i32 res = gpusolve(c);
u64 stop = utime();
tottime += (stop - start);
freecnf(c);
if (res == 0) passed++;
}
printf("Passed %u / 1000 tests\n", passed);
printf("Took %lf s total, %lf s on avg\n", ((f64) tottime) / 1000000.0, ((f64) tottime) / 1000000000.0);
}
i32 runuf50() {
printf("Running against uf50\n");
u32 passed = 0;
u64 tottime = 0;
for (u32 i = 0; i < 1000; ++i) {
char buf[128];
i32 len = sprintf(buf, "/home/lev/Downloads/uf50/uf50-0%u.cnf", i + 1);
cnf* c = readDIMACS(buf);
sortlastnum(c, c->litcnt);
u64 start = utime();
i32 res = gpusolve(c);
u64 stop = utime();
tottime += (stop - start);
freecnf(c);
if (res == 0) passed++;
}
printf("Passed %u / 1000 tests\n", passed);
printf("Took %lf s total, %lf s on avg\n", ((f64) tottime) / 1000000.0, ((f64) tottime) / 1000000000.0);
}
i32 runuuf50() {
printf("Running against uuf50\n");
u32 passed = 0;
u64 tottime = 0;
for (u32 i = 0; i < 1000; ++i) {
char buf[128];
i32 len = sprintf(buf, "/home/lev/Downloads/uuf50/uuf50-0%u.cnf", i + 1);
cnf* c = readDIMACS(buf);
sortlastnum(c, c->litcnt);
u64 start = utime();
i32 res = gpusolve(c);
u64 stop = utime();
tottime += (stop - start);
freecnf(c);
if (res == 0) passed++;
}
printf("Passed %u / 1000 tests\n", passed);
printf("Took %lf s total, %lf s on avg\n", ((f64) tottime) / 1000000.0, ((f64) tottime) / 1000000000.0);
}

8
tests/masterTest.h Normal file
View File

@@ -0,0 +1,8 @@
#pragma once
#include "../types.h"
i32 runTests();
i32 runuf20();
i32 runuf50();
i32 runuuf50();