From 7ce1e80739e9d647598be38f3903952601e7c076 Mon Sep 17 00:00:00 2001 From: gothictomato Date: Sun, 17 Jul 2022 21:40:34 -0400 Subject: [PATCH 1/2] Added test cases Signed-off-by: gothictomato --- CMakeLists.txt | 4 +- gpusolver.c | 168 ++++----------------------------------------- main.c | 3 + tests/masterTest.c | 87 +++++++++++++++++++++++ tests/masterTest.h | 8 +++ 5 files changed, 114 insertions(+), 156 deletions(-) create mode 100644 tests/masterTest.c create mode 100644 tests/masterTest.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f71281..de2aef4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) \ No newline at end of file diff --git a/gpusolver.c b/gpusolver.c index 52e8906..63aa37b 100644 --- a/gpusolver.c +++ b/gpusolver.c @@ -2,146 +2,6 @@ #include #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); diff --git a/main.c b/main.c index 8f4372f..cf4647c 100644 --- a/main.c +++ b/main.c @@ -2,8 +2,11 @@ #include "cnf.h" #include "gpusolver.h" #include "time.h" +#include "tests/masterTest.h" int main() { + runuf20(); + return 0; /* srand( utime()); u32 cnt = 4096; diff --git a/tests/masterTest.c b/tests/masterTest.c new file mode 100644 index 0000000..6a7af0f --- /dev/null +++ b/tests/masterTest.c @@ -0,0 +1,87 @@ +#include "masterTest.h" +#include +#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); +} \ No newline at end of file diff --git a/tests/masterTest.h b/tests/masterTest.h new file mode 100644 index 0000000..62b01c4 --- /dev/null +++ b/tests/masterTest.h @@ -0,0 +1,8 @@ +#pragma once +#include "../types.h" + +i32 runTests(); + +i32 runuf20(); +i32 runuf50(); +i32 runuuf50(); \ No newline at end of file From 511ab6c8d8eb19c0c3cc6f68dcc1c3b7cf61bc01 Mon Sep 17 00:00:00 2001 From: gothictomato Date: Sun, 17 Jul 2022 21:42:47 -0400 Subject: [PATCH 2/2] Changed main.c back to normal run mode from testing Signed-off-by: gothictomato --- main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.c b/main.c index cf4647c..9b3e030 100644 --- a/main.c +++ b/main.c @@ -5,8 +5,6 @@ #include "tests/masterTest.h" int main() { - runuf20(); - return 0; /* srand( utime()); u32 cnt = 4096; @@ -28,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);