From ce46013ba795f4c1863d63140aa05c4fa8e013a2 Mon Sep 17 00:00:00 2001 From: dmed256 Date: Sun, 2 Sep 2018 00:11:49 -0500 Subject: [PATCH] [#204][Kernel] Kernel compilation now creates .success files to safely avoid locks --- include/occa/io/cache.hpp | 6 ++++++ include/occa/io/utils.hpp | 1 - src/io/cache.cpp | 19 +++++++++++++++++ src/mode/cuda/device.cpp | 41 +++++++++++++++++++++--------------- src/mode/hip/device.cpp | 41 +++++++++++++++++++++--------------- src/mode/opencl/device.cpp | 43 ++++++++++++++++++++++---------------- src/mode/serial/device.cpp | 27 +++++++++++++----------- 7 files changed, 113 insertions(+), 65 deletions(-) diff --git a/include/occa/io/cache.hpp b/include/occa/io/cache.hpp index b4e5fc726..ac1210095 100644 --- a/include/occa/io/cache.hpp +++ b/include/occa/io/cache.hpp @@ -50,6 +50,12 @@ namespace occa { const hash_t &hash, const std::string &header = ""); + void markCachedFileComplete(const std::string &hashDir, + const std::string &filename); + + bool cachedFileIsComplete(const std::string &hashDir, + const std::string &filename); + void setBuildProps(occa::json &props); void writeBuildFile(const std::string &filename, diff --git a/include/occa/io/utils.hpp b/include/occa/io/utils.hpp index b1669b98e..f10b4517d 100644 --- a/include/occa/io/utils.hpp +++ b/include/occa/io/utils.hpp @@ -41,7 +41,6 @@ namespace occa { namespace io { const std::string& cachePath(); - const std::string& libraryPath(); void endWithSlash(std::string &dir); diff --git a/src/io/cache.cpp b/src/io/cache.cpp index 88fd0b377..09a3db0b4 100644 --- a/src/io/cache.cpp +++ b/src/io/cache.cpp @@ -142,6 +142,25 @@ namespace occa { return sourceFile; } + void markCachedFileComplete(const std::string &hashDir, + const std::string &filename) { + std::string successFile = hashDir; + successFile += ".success/"; + sys::mkpath(successFile); + + successFile += filename; + io::write(successFile, ""); + } + + bool cachedFileIsComplete(const std::string &hashDir, + const std::string &filename) { + std::string successFile = hashDir; + successFile += ".success/"; + successFile += filename; + + return io::exists(successFile); + } + void setBuildProps(occa::json &props) { props["date"] = sys::date(); props["human_date"] = sys::humanDate(); diff --git a/src/mode/cuda/device.cpp b/src/mode/cuda/device.cpp index c07273321..cd1deb333 100644 --- a/src/mode/cuda/device.cpp +++ b/src/mode/cuda/device.cpp @@ -222,11 +222,12 @@ namespace occa { bool foundBinary = true; bool usingOKL = kernelProps.get("okl", true); - io::lock_t lock(kernelHash, "cuda-kernel"); - if (lock.isMine()) { - if (io::isFile(binaryFilename)) { - lock.release(); - } else { + // Check if binary exists and is finished + io::lock_t lock; + if (!io::cachedFileIsComplete(hashDir, kc::binaryFile) || + !io::isFile(binaryFilename)) { + lock = io::lock_t(kernelHash, "cuda-kernel"); + if (lock.isMine()) { foundBinary = false; } } @@ -309,6 +310,7 @@ namespace occa { lock); // Regular CUDA Kernel + modeKernel_t *k = NULL; if (!launcherKernel) { CUmodule cuModule; CUfunction cuFunction; @@ -328,20 +330,25 @@ namespace occa { OCCA_CUDA_ERROR("Kernel [" + kernelName + "]: Loading Function", error); } - return new kernel(this, - kernelName, - sourceFilename, - cuModule, - cuFunction, - kernelProps); + k = new kernel(this, + kernelName, + sourceFilename, + cuModule, + cuFunction, + kernelProps); + } else { + k = buildOKLKernelFromBinary(hashDir, + kernelName, + hostMetadata, + deviceMetadata, + kernelProps, + lock); } - return buildOKLKernelFromBinary(hashDir, - kernelName, - hostMetadata, - deviceMetadata, - kernelProps, - lock); + if (k) { + io::markCachedFileComplete(hashDir, kc::binaryFile); + } + return k; } void device::setArchCompilerFlags(occa::properties &kernelProps) { diff --git a/src/mode/hip/device.cpp b/src/mode/hip/device.cpp index a0c411816..9fc458d0f 100644 --- a/src/mode/hip/device.cpp +++ b/src/mode/hip/device.cpp @@ -228,11 +228,12 @@ namespace occa { bool foundBinary = true; bool usingOKL = kernelProps.get("okl", true); - io::lock_t lock(kernelHash, "hip-kernel"); - if (lock.isMine()) { - if (io::isFile(binaryFilename)) { - lock.release(); - } else { + // Check if binary exists and is finished + io::lock_t lock; + if (!io::cachedFileIsComplete(hashDir, kc::binaryFile) || + !io::isFile(binaryFilename)) { + lock = io::lock_t(kernelHash, "hip-kernel"); + if (lock.isMine()) { foundBinary = false; } } @@ -315,6 +316,7 @@ namespace occa { lock); // Regular HIP Kernel + modeKernel_t *k = NULL; if (!launcherKernel) { hipModule_t hipModule; hipFunction_t hipFunction; @@ -334,20 +336,25 @@ namespace occa { OCCA_HIP_ERROR("Kernel [" + kernelName + "]: Loading Function", error); } - return new kernel(this, - kernelName, - sourceFilename, - hipModule, - hipFunction, - kernelProps); + k = new kernel(this, + kernelName, + sourceFilename, + hipModule, + hipFunction, + kernelProps); + } else { + k = buildOKLKernelFromBinary(hashDir, + kernelName, + hostMetadata, + deviceMetadata, + kernelProps, + lock); } - return buildOKLKernelFromBinary(hashDir, - kernelName, - hostMetadata, - deviceMetadata, - kernelProps, - lock); + if (k) { + io::markCachedFileComplete(hashDir, kc::binaryFile); + } + return k; } void device::setArchCompilerFlags(occa::properties &kernelProps) { diff --git a/src/mode/opencl/device.cpp b/src/mode/opencl/device.cpp index 63b4b300b..cfce5a907 100644 --- a/src/mode/opencl/device.cpp +++ b/src/mode/opencl/device.cpp @@ -233,11 +233,12 @@ namespace occa { clInfo.clDevice = clDevice; clInfo.clContext = clContext; - io::lock_t lock(kernelHash, "opencl-kernel"); - if (lock.isMine()) { - if (io::isFile(binaryFilename)) { - lock.release(); - } else { + // Check if binary exists and is finished + io::lock_t lock; + if (!io::cachedFileIsComplete(hashDir, kc::binaryFile) || + !io::isFile(binaryFilename)) { + lock = io::lock_t(kernelHash, "opencl-kernel"); + if (lock.isMine()) { foundBinary = false; } } @@ -331,25 +332,31 @@ namespace occa { lock); // Regular OpenCL Kernel + modeKernel_t *k = NULL; if (!launcherKernel) { opencl::buildKernelFromProgram(clInfo, kernelName, lock); - return new kernel(this, - kernelName, - sourceFilename, - clDevice, - clInfo.clKernel, - kernelProps); + k = new kernel(this, + kernelName, + sourceFilename, + clDevice, + clInfo.clKernel, + kernelProps); + } else { + k = buildOKLKernelFromBinary(clInfo, + hashDir, + kernelName, + hostMetadata, + deviceMetadata, + kernelProps, + lock); } - return buildOKLKernelFromBinary(clInfo, - hashDir, - kernelName, - hostMetadata, - deviceMetadata, - kernelProps, - lock); + if (k) { + io::markCachedFileComplete(hashDir, kc::binaryFile); + } + return k; } modeKernel_t* device::buildOKLKernelFromBinary(info_t &clInfo, diff --git a/src/mode/serial/device.cpp b/src/mode/serial/device.cpp index 72c474e2e..c5ab8600d 100644 --- a/src/mode/serial/device.cpp +++ b/src/mode/serial/device.cpp @@ -188,20 +188,22 @@ namespace occa { const hash_t kernelHash, const occa::properties &kernelProps) { const std::string hashDir = io::hashDir(filename, kernelHash); - std::string binaryFilename = hashDir + kc::binaryFile; + // Binary name depends if this is being used as the launcher kernel for + // GPU-style kernels + const std::string &kcBinaryFile = ( + (filename != (hashDir + kc::hostSourceFile)) + ? kc::binaryFile + : kc::hostBinaryFile + ); + std::string binaryFilename = hashDir + kcBinaryFile; bool foundBinary = true; - // This is a launcher kernel - // TODO: Clean this up - if (startsWith(filename, hashDir)) { - binaryFilename = io::dirname(filename) + kc::hostBinaryFile; - } - - io::lock_t lock(kernelHash, "serial-kernel"); - if (lock.isMine()) { - if (io::isFile(binaryFilename)) { - lock.release(); - } else { + // Check if binary exists and is finished + io::lock_t lock; + if (!io::cachedFileIsComplete(hashDir, kcBinaryFile) || + !io::isFile(binaryFilename)) { + lock = io::lock_t(kernelHash, "serial-kernel"); + if (lock.isMine()) { foundBinary = false; } } @@ -300,6 +302,7 @@ namespace occa { kernelName, kernelProps); if (k) { + io::markCachedFileComplete(hashDir, kcBinaryFile); k->sourceFilename = filename; } return k;