From 61fab0340cd4a56bb9f5f8a03eaaecf3dbb88486 Mon Sep 17 00:00:00 2001 From: Evghenii Date: Wed, 13 Nov 2013 17:07:55 +0100 Subject: [PATCH] working on sort --- examples_cuda/sort/Makefile | 2 +- examples_cuda/sort/Makefile_gpu | 52 +++ examples_cuda/sort/drvapi_error_string.h | 370 +++++++++++++++++++++ examples_cuda/sort/sort | Bin 132221 -> 58115 bytes examples_cuda/sort/sort.cpp | 26 +- examples_cuda/sort/sort1.cu | 265 +++++++++++++++ examples_cuda/sort/sort1.ispc | 275 +++++++++++++++ examples_cuda/sort/sort_cu.cpp | 405 +++++++++++++++++++++++ 8 files changed, 1391 insertions(+), 4 deletions(-) create mode 100644 examples_cuda/sort/Makefile_gpu create mode 100644 examples_cuda/sort/drvapi_error_string.h create mode 100644 examples_cuda/sort/sort1.cu create mode 100644 examples_cuda/sort/sort1.ispc create mode 100644 examples_cuda/sort/sort_cu.cpp diff --git a/examples_cuda/sort/Makefile b/examples_cuda/sort/Makefile index cf6bffa4..09ae50e5 100644 --- a/examples_cuda/sort/Makefile +++ b/examples_cuda/sort/Makefile @@ -2,7 +2,7 @@ EXAMPLE=sort CPP_SRC=sort.cpp sort_serial.cpp ISPC_SRC=sort.ispc -ISPC_IA_TARGETS=sse2,sse4-x2,avx +ISPC_IA_TARGETS=avx ISPC_ARM_TARGETS=neon #ISPC_FLAGS=-DDEBUG diff --git a/examples_cuda/sort/Makefile_gpu b/examples_cuda/sort/Makefile_gpu new file mode 100644 index 00000000..af65c30f --- /dev/null +++ b/examples_cuda/sort/Makefile_gpu @@ -0,0 +1,52 @@ +PROG=sort_cu +ISPC_SRC=sort1.ispc +CXX_SRC=sort_cu.cpp sort_serial.cpp + +CXX=g++ +CXXFLAGS=-O3 -I$(CUDATK)/include +LD=g++ +LDFLAGS=-lcuda + +ISPC=ispc +ISPCFLAGS=-O3 --math-lib=default --target=nvptx64,avx + +LLVM32 = $(HOME)/usr/local/llvm/bin-3.2 +LLVM = $(HOME)/usr/local/llvm/bin-3.3 +PTXGEN = $(HOME)/ptxgen + +LLVM32DIS=$(LLVM32)/bin/llvm-dis + +.SUFFIXES: .bc .o .ptx .cu _ispc_nvptx64.bc + + +ISPC_OBJ=$(ISPC_SRC:%.ispc=%_ispc.o) +ISPC_BC=$(ISPC_SRC:%.ispc=%_ispc_nvptx64.bc) +PTXSRC=$(ISPC_SRC:%.ispc=%_ispc_nvptx64.ptx) +CXX_OBJ=$(CXX_SRC:%.cpp=%.o) + +all: $(PROG) + + +$(PROG): $(CXX_OBJ) kernel.ptx + /bin/cp kernel.ptx __kernels.ptx + $(LD) -o $@ $(CXX_OBJ) $(LDFLAGS) + +%.o: %.cpp + $(CXX) $(CXXFLAGS) -o $@ -c $< + + +%_ispc_nvptx64.bc: %.ispc + $(ISPC) $(ISPCFLAGS) --emit-llvm -o `basename $< .ispc`_ispc.bc -h `basename $< .ispc`_ispc.h $< --emit-llvm + +%.ptx: %.bc + $(LLVM32DIS) $< + $(PTXGEN) `basename $< .bc`.ll > $@ + +kernel.ptx: $(PTXSRC) + cat $^ > kernel.ptx + +clean: + /bin/rm -rf *.ptx *.bc *.ll $(PROG) + + + diff --git a/examples_cuda/sort/drvapi_error_string.h b/examples_cuda/sort/drvapi_error_string.h new file mode 100644 index 00000000..ce85f152 --- /dev/null +++ b/examples_cuda/sort/drvapi_error_string.h @@ -0,0 +1,370 @@ +/* + * Copyright 1993-2012 NVIDIA Corporation. All rights reserved. + * + * Please refer to the NVIDIA end user license agreement (EULA) associated + * with this source code for terms and conditions that govern your use of + * this software. Any use, reproduction, disclosure, or distribution of + * this software and related documentation outside the terms of the EULA + * is strictly prohibited. + * + */ + +#ifndef _DRVAPI_ERROR_STRING_H_ +#define _DRVAPI_ERROR_STRING_H_ + +#include +#include +#include + +// Error Code string definitions here +typedef struct +{ + char const *error_string; + int error_id; +} s_CudaErrorStr; + +/** + * Error codes + */ +static s_CudaErrorStr sCudaDrvErrorString[] = +{ + /** + * The API call returned with no errors. In the case of query calls, this + * can also mean that the operation being queried is complete (see + * ::cuEventQuery() and ::cuStreamQuery()). + */ + { "CUDA_SUCCESS", 0 }, + + /** + * This indicates that one or more of the parameters passed to the API call + * is not within an acceptable range of values. + */ + { "CUDA_ERROR_INVALID_VALUE", 1 }, + + /** + * The API call failed because it was unable to allocate enough memory to + * perform the requested operation. + */ + { "CUDA_ERROR_OUT_OF_MEMORY", 2 }, + + /** + * This indicates that the CUDA driver has not been initialized with + * ::cuInit() or that initialization has failed. + */ + { "CUDA_ERROR_NOT_INITIALIZED", 3 }, + + /** + * This indicates that the CUDA driver is in the process of shutting down. + */ + { "CUDA_ERROR_DEINITIALIZED", 4 }, + + /** + * This indicates profiling APIs are called while application is running + * in visual profiler mode. + */ + { "CUDA_ERROR_PROFILER_DISABLED", 5 }, + /** + * This indicates profiling has not been initialized for this context. + * Call cuProfilerInitialize() to resolve this. + */ + { "CUDA_ERROR_PROFILER_NOT_INITIALIZED", 6 }, + /** + * This indicates profiler has already been started and probably + * cuProfilerStart() is incorrectly called. + */ + { "CUDA_ERROR_PROFILER_ALREADY_STARTED", 7 }, + /** + * This indicates profiler has already been stopped and probably + * cuProfilerStop() is incorrectly called. + */ + { "CUDA_ERROR_PROFILER_ALREADY_STOPPED", 8 }, + /** + * This indicates that no CUDA-capable devices were detected by the installed + * CUDA driver. + */ + { "CUDA_ERROR_NO_DEVICE (no CUDA-capable devices were detected)", 100 }, + + /** + * This indicates that the device ordinal supplied by the user does not + * correspond to a valid CUDA device. + */ + { "CUDA_ERROR_INVALID_DEVICE (device specified is not a valid CUDA device)", 101 }, + + + /** + * This indicates that the device kernel image is invalid. This can also + * indicate an invalid CUDA module. + */ + { "CUDA_ERROR_INVALID_IMAGE", 200 }, + + /** + * This most frequently indicates that there is no context bound to the + * current thread. This can also be returned if the context passed to an + * API call is not a valid handle (such as a context that has had + * ::cuCtxDestroy() invoked on it). This can also be returned if a user + * mixes different API versions (i.e. 3010 context with 3020 API calls). + * See ::cuCtxGetApiVersion() for more details. + */ + { "CUDA_ERROR_INVALID_CONTEXT", 201 }, + + /** + * This indicated that the context being supplied as a parameter to the + * API call was already the active context. + * \deprecated + * This error return is deprecated as of CUDA 3.2. It is no longer an + * error to attempt to push the active context via ::cuCtxPushCurrent(). + */ + { "CUDA_ERROR_CONTEXT_ALREADY_CURRENT", 202 }, + + /** + * This indicates that a map or register operation has failed. + */ + { "CUDA_ERROR_MAP_FAILED", 205 }, + + /** + * This indicates that an unmap or unregister operation has failed. + */ + { "CUDA_ERROR_UNMAP_FAILED", 206 }, + + /** + * This indicates that the specified array is currently mapped and thus + * cannot be destroyed. + */ + { "CUDA_ERROR_ARRAY_IS_MAPPED", 207 }, + + /** + * This indicates that the resource is already mapped. + */ + { "CUDA_ERROR_ALREADY_MAPPED", 208 }, + + /** + * This indicates that there is no kernel image available that is suitable + * for the device. This can occur when a user specifies code generation + * options for a particular CUDA source file that do not include the + * corresponding device configuration. + */ + { "CUDA_ERROR_NO_BINARY_FOR_GPU", 209 }, + + /** + * This indicates that a resource has already been acquired. + */ + { "CUDA_ERROR_ALREADY_ACQUIRED", 210 }, + + /** + * This indicates that a resource is not mapped. + */ + { "CUDA_ERROR_NOT_MAPPED", 211 }, + + /** + * This indicates that a mapped resource is not available for access as an + * array. + */ + { "CUDA_ERROR_NOT_MAPPED_AS_ARRAY", 212 }, + + /** + * This indicates that a mapped resource is not available for access as a + * pointer. + */ + { "CUDA_ERROR_NOT_MAPPED_AS_POINTER", 213 }, + + /** + * This indicates that an uncorrectable ECC error was detected during + * execution. + */ + { "CUDA_ERROR_ECC_UNCORRECTABLE", 214 }, + + /** + * This indicates that the ::CUlimit passed to the API call is not + * supported by the active device. + */ + { "CUDA_ERROR_UNSUPPORTED_LIMIT", 215 }, + + /** + * This indicates that the ::CUcontext passed to the API call can + * only be bound to a single CPU thread at a time but is already + * bound to a CPU thread. + */ + { "CUDA_ERROR_CONTEXT_ALREADY_IN_USE", 216 }, + + /** + * This indicates that peer access is not supported across the given + * devices. + */ + { "CUDA_ERROR_PEER_ACCESS_UNSUPPORTED", 217}, + + /** + * This indicates that the device kernel source is invalid. + */ + { "CUDA_ERROR_INVALID_SOURCE", 300 }, + + /** + * This indicates that the file specified was not found. + */ + { "CUDA_ERROR_FILE_NOT_FOUND", 301 }, + + /** + * This indicates that a link to a shared object failed to resolve. + */ + { "CUDA_ERROR_SHARED_OBJECT_SYMBOL_NOT_FOUND", 302 }, + + /** + * This indicates that initialization of a shared object failed. + */ + { "CUDA_ERROR_SHARED_OBJECT_INIT_FAILED", 303 }, + + /** + * This indicates that an OS call failed. + */ + { "CUDA_ERROR_OPERATING_SYSTEM", 304 }, + + + /** + * This indicates that a resource handle passed to the API call was not + * valid. Resource handles are opaque types like ::CUstream and ::CUevent. + */ + { "CUDA_ERROR_INVALID_HANDLE", 400 }, + + + /** + * This indicates that a named symbol was not found. Examples of symbols + * are global/constant variable names, texture names }, and surface names. + */ + { "CUDA_ERROR_NOT_FOUND", 500 }, + + + /** + * This indicates that asynchronous operations issued previously have not + * completed yet. This result is not actually an error, but must be indicated + * differently than ::CUDA_SUCCESS (which indicates completion). Calls that + * may return this value include ::cuEventQuery() and ::cuStreamQuery(). + */ + { "CUDA_ERROR_NOT_READY", 600 }, + + + /** + * An exception occurred on the device while executing a kernel. Common + * causes include dereferencing an invalid device pointer and accessing + * out of bounds shared memory. The context cannot be used }, so it must + * be destroyed (and a new one should be created). All existing device + * memory allocations from this context are invalid and must be + * reconstructed if the program is to continue using CUDA. + */ + { "CUDA_ERROR_LAUNCH_FAILED", 700 }, + + /** + * This indicates that a launch did not occur because it did not have + * appropriate resources. This error usually indicates that the user has + * attempted to pass too many arguments to the device kernel, or the + * kernel launch specifies too many threads for the kernel's register + * count. Passing arguments of the wrong size (i.e. a 64-bit pointer + * when a 32-bit int is expected) is equivalent to passing too many + * arguments and can also result in this error. + */ + { "CUDA_ERROR_LAUNCH_OUT_OF_RESOURCES", 701 }, + + /** + * This indicates that the device kernel took too long to execute. This can + * only occur if timeouts are enabled - see the device attribute + * ::CU_DEVICE_ATTRIBUTE_KERNEL_EXEC_TIMEOUT for more information. The + * context cannot be used (and must be destroyed similar to + * ::CUDA_ERROR_LAUNCH_FAILED). All existing device memory allocations from + * this context are invalid and must be reconstructed if the program is to + * continue using CUDA. + */ + { "CUDA_ERROR_LAUNCH_TIMEOUT", 702 }, + + /** + * This error indicates a kernel launch that uses an incompatible texturing + * mode. + */ + { "CUDA_ERROR_LAUNCH_INCOMPATIBLE_TEXTURING", 703 }, + + /** + * This error indicates that a call to ::cuCtxEnablePeerAccess() is + * trying to re-enable peer access to a context which has already + * had peer access to it enabled. + */ + { "CUDA_ERROR_PEER_ACCESS_ALREADY_ENABLED", 704 }, + + /** + * This error indicates that ::cuCtxDisablePeerAccess() is + * trying to disable peer access which has not been enabled yet + * via ::cuCtxEnablePeerAccess(). + */ + { "CUDA_ERROR_PEER_ACCESS_NOT_ENABLED", 705 }, + + /** + * This error indicates that the primary context for the specified device + * has already been initialized. + */ + { "CUDA_ERROR_PRIMARY_CONTEXT_ACTIVE", 708 }, + + /** + * This error indicates that the context current to the calling thread + * has been destroyed using ::cuCtxDestroy }, or is a primary context which + * has not yet been initialized. + */ + { "CUDA_ERROR_CONTEXT_IS_DESTROYED", 709 }, + + /** + * A device-side assert triggered during kernel execution. The context + * cannot be used anymore, and must be destroyed. All existing device + * memory allocations from this context are invalid and must be + * reconstructed if the program is to continue using CUDA. + */ + { "CUDA_ERROR_ASSERT", 710 }, + + /** + * This error indicates that the hardware resources required to enable + * peer access have been exhausted for one or more of the devices + * passed to ::cuCtxEnablePeerAccess(). + */ + { "CUDA_ERROR_TOO_MANY_PEERS", 711 }, + + /** + * This error indicates that the memory range passed to ::cuMemHostRegister() + * has already been registered. + */ + { "CUDA_ERROR_HOST_MEMORY_ALREADY_REGISTERED", 712 }, + + /** + * This error indicates that the pointer passed to ::cuMemHostUnregister() + * does not correspond to any currently registered memory region. + */ + { "CUDA_ERROR_HOST_MEMORY_NOT_REGISTERED", 713 }, + + /** + * This error indicates that the attempted operation is not permitted. + */ + { "CUDA_ERROR_NOT_PERMITTED", 800 }, + + /** + * This error indicates that the attempted operation is not supported + * on the current system or device. + */ + { "CUDA_ERROR_NOT_SUPPORTED", 801 }, + + /** + * This indicates that an unknown internal error has occurred. + */ + { "CUDA_ERROR_UNKNOWN", 999 }, + { NULL, -1 } +}; + +// This is just a linear search through the array, since the error_id's are not +// always ocurring consecutively +const char * getCudaDrvErrorString(CUresult error_id) +{ + int index = 0; + while (sCudaDrvErrorString[index].error_id != error_id && + sCudaDrvErrorString[index].error_id != -1) + { + index++; + } + if (sCudaDrvErrorString[index].error_id == error_id) + return (const char *)sCudaDrvErrorString[index].error_string; + else + return (const char *)"CUDA_ERROR not found!"; +} + +#endif diff --git a/examples_cuda/sort/sort b/examples_cuda/sort/sort index 51e36ea7b7b20a3cf67c7a5c683e38b6807c2329..d148e465a4b211c1b0af13bfbabd34128d46fb56 100755 GIT binary patch literal 58115 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 z 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≧?yDI>wERZ_>Wyhzc>{k*g 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 diff --git a/examples_cuda/sort/sort.cpp b/examples_cuda/sort/sort.cpp index f5e4264a..37a5c289 100644 --- a/examples_cuda/sort/sort.cpp +++ b/examples_cuda/sort/sort.cpp @@ -41,6 +41,20 @@ #include "../timing.h" #include "sort_ispc.h" +#include +static inline double rtc(void) +{ + struct timeval Tvalue; + double etime; + struct timezone dummy; + + gettimeofday(&Tvalue,&dummy); + etime = (double) Tvalue.tv_sec + + 1.e-6*((double) Tvalue.tv_usec); + return etime; +} + + using namespace ispc; extern void sort_serial (int n, unsigned int code[], int order[]); @@ -71,26 +85,30 @@ int main (int argc, char *argv[]) { int i, j, n = argc == 1 ? 1000000 : atoi(argv[1]), m = n < 100 ? 1 : 50, l = n < 100 ? n : RAND_MAX; double tISPC1 = 0.0, tISPC2 = 0.0, tSerial = 0.0; + printf("n= %d \n", n); unsigned int *code = new unsigned int [n]; int *order = new int [n]; srand (0); +#if 0 for (i = 0; i < m; i ++) { for (j = 0; j < n; j ++) code [j] = random() % l; reset_and_start_timer(); + const double t0 = rtc(); sort_ispc (n, code, order, 1); - tISPC1 += get_elapsed_mcycles(); + tISPC1 += (rtc() - t0); //get_elapsed_mcycles(); if (argc != 3) progressbar (i, m); } printf("[sort ispc]:\t[%.3f] million cycles\n", tISPC1); +#endif srand (0); @@ -100,9 +118,10 @@ int main (int argc, char *argv[]) reset_and_start_timer(); + const double t0 = rtc(); sort_ispc (n, code, order, 0); - tISPC2 += get_elapsed_mcycles(); + tISPC2 += (rtc() - t0); // get_elapsed_mcycles(); if (argc != 3) progressbar (i, m); @@ -118,9 +137,10 @@ int main (int argc, char *argv[]) reset_and_start_timer(); + const double t0 = rtc(); sort_serial (n, code, order); - tSerial += get_elapsed_mcycles(); + tSerial += (rtc() - t0);//get_elapsed_mcycles(); if (argc != 3) progressbar (i, m); diff --git a/examples_cuda/sort/sort1.cu b/examples_cuda/sort/sort1.cu new file mode 100644 index 00000000..b35ba506 --- /dev/null +++ b/examples_cuda/sort/sort1.cu @@ -0,0 +1,265 @@ +/* + Copyright (c) 2013, Durham University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Durham University nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Author: Tomasz Koziara */ + +#define programCount 32 +#define programIndex (threadIdx.x & 31) +#define taskIndex (blockIdx.x*4 + (threadIdx.x >> 5)) +#define taskCount (gridDim.x*4) +#define cfor for +#define cif if + +#define int8 char +#define int64 long +#define sync cudaDeviceSynchronize(); + +__device__ inline int nbx(const int n) { return (n - 1) / 4 + 1; } + +__global__ void histogram ( int span, int n, int64 code[], int pass, int hist[]) +{ + if (taskIndex >= taskCount) return; + int start = taskIndex*span; + int end = taskIndex == taskCount-1 ? n : start+span; + int strip = (end-start)/programCount; + int tail = (end-start)%programCount; + int i = programCount*taskIndex + programIndex; + int g [256]; + + cfor (int j = 0; j < 256; j ++) + { + g[j] = 0; + } + + cfor (int k = start+programIndex*strip; k < start+(programIndex+1)*strip; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + g[c[pass]] ++; + } + + if (programIndex == programCount-1) /* remainder is processed by the last lane */ + { + for (int k = start+programCount*strip; k < start+programCount*strip+tail; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + g[c[pass]] ++; + } + } + + cfor (int j = 0; j < 256; j ++) + { + hist[j*programCount*taskCount+i] = g[j]; + } +} + +__global__ void permutation ( int span, int n, int64 code[], int pass, int hist[], int64 perm[]) +{ + if (taskIndex >= taskCount) return; + int start = taskIndex*span; + int end = taskIndex == taskCount-1 ? n : start+span; + int strip = (end-start)/programCount; + int tail = (end-start)%programCount; + int i = programCount*taskIndex + programIndex; + int g [256]; + + cfor (int j = 0; j < 256; j ++) + { + g[j] = hist[j*programCount*taskCount+i]; + } + + cfor (int k = start+programIndex*strip; k < start+(programIndex+1)*strip; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + int l = g[c[pass]]; + + perm[l] = code[k]; + + g[c[pass]] = l+1; + } + + if (programIndex == programCount-1) /* remainder is processed by the last lane */ + { + for (int k = start+programCount*strip; k < start+programCount*strip+tail; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + int l = g[c[pass]]; + + perm[l] = code[k]; + + g[c[pass]] = l+1; + } + } +} + +__global__ void copy ( int span, int n, int64 from[], int64 to[]) +{ + if (taskIndex >= taskCount) return; + int start = taskIndex*span; + int end = taskIndex == taskCount-1 ? n : start+span; + + for (int i = programIndex + start; i < end; i += programCount) + if (i < end) + { + to[i] = from[i]; + } +} + +__global__ void pack ( int span, int n, unsigned int code[], int64 pair[]) +{ + if (taskIndex >= taskCount) return; + int start = taskIndex*span; + int end = taskIndex == taskCount-1 ? n : start+span; + + for (int i = programIndex + start; i < end; i += programCount) + if (i < end) + { + pair[i] = ((int64)i<<32)+code[i]; + } +} + +__global__ void unpack ( int span, int n, int64 pair[], int unsigned code[], int order[]) +{ + if (taskIndex >= taskCount) return; + int start = taskIndex*span; + int end = taskIndex == taskCount-1 ? n : start+span; + + for (int i = programIndex + start; i < end; i += programCount) + if (i < end) + { + code[i] = pair[i]; + order[i] = pair[i]>>32; + } +} + +__global__ void addup ( int h[], int g[]) +{ + if (taskIndex >= taskCount) return; + int * u = &h[256*programCount*taskIndex]; + int i, x, y = 0; + + for (i = 0; i < 256*programCount; i ++) + { + x = u[i]; + u[i] = y; + y += x; + } + + g[taskIndex] = y; +} + +__global__ void bumpup ( int h[], int g[]) +{ + if (taskIndex >= taskCount) return; + int * u = &h[256*programCount*taskIndex]; + int z = g[taskIndex]; + + for (int i = programIndex; i < 256*programCount; i += programCount) + { + u[i] += z; + } +} + +__device__ +static void prefix_sum ( int num, int h[]) +{ + int * g = new int [num+1]; + int i; + +// launch[num] addup (h, g+1); + if(programIndex == 0) + addup<<>>(h,g+1); + sync; + + for (g[0] = 0, i = 1; i < num; i ++) g[i] += g[i-1]; + +// launch[num] bumpup (h, g); + if(programIndex == 0) + bumpup<<>>(h,g); + sync; + + delete g; +} + +extern "C" __global__ +void sort_ispc ( int n, unsigned int code[], int order[], int ntasks) +{ + int num = ntasks < 1 ? 13*4*8 : ntasks; + int span = n / num; + int hsize = 256*programCount*num; + int * hist = new int [hsize]; + int64 * pair = new int64 [n]; + int64 * temp = new int64 [n]; + int pass, i; + + +// launch[num] pack (span, n, code, pair); + if(programIndex == 0) + pack<<>>(span, n, code, pair); + sync; + +#if 0 + for (pass = 0; pass < 4; pass ++) + { +// launch[num] histogram (span, n, pair, pass, hist); + if(programIndex == 0) + histogram<<>>(span, n, pair, pass, hist); + sync; + + prefix_sum (num, hist); + +// launch[num] permutation (span, n, pair, pass, hist, temp); + if(programIndex == 0) + permutation<<>> (span, n, pair, pass, hist, temp); + sync; + +/// launch[num] copy (span, n, temp, pair); + if(programIndex == 0) + copy<<>> (span, n, temp, pair); + sync; + } + +/// launch[num] unpack (span, n, pair, code, order); + if(programIndex == 0) + unpack<<>> (span, n, pair, code, order); + sync; +#endif + + + delete hist; + delete pair; + delete temp; +} diff --git a/examples_cuda/sort/sort1.ispc b/examples_cuda/sort/sort1.ispc new file mode 100644 index 00000000..0c500ed4 --- /dev/null +++ b/examples_cuda/sort/sort1.ispc @@ -0,0 +1,275 @@ +/* + Copyright (c) 2013, Durham University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Durham University nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Author: Tomasz Koziara */ + +#ifdef __NVPTX__ +#warning "emitting DEVICE code" +#define programCount warpSize() +#define programIndex laneIndex() +#define taskIndex blockIndex0() +#define taskCount blockCount0() +#define cfor for +#define cif if +#else +#warning "emitting HOST code" +#endif + +task void histogram (uniform int span, uniform int n, uniform int64 code[], uniform int pass, uniform int hist[]) +{ + if (taskIndex >= taskCount) return; + uniform int start = taskIndex*span; + uniform int end = taskIndex == taskCount-1 ? n : start+span; + uniform int strip = (end-start)/programCount; + uniform int tail = (end-start)%programCount; + int i = programCount*taskIndex + programIndex; + int g [256]; + + cfor (int j = 0; j < 256; j ++) + { + g[j] = 0; + } + + cfor (int k = start+programIndex*strip; k < start+(programIndex+1)*strip; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + g[c[pass]] ++; + } + + if (programIndex == programCount-1) /* remainder is processed by the last lane */ + { + for (int k = start+programCount*strip; k < start+programCount*strip+tail; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + g[c[pass]] ++; + } + } + + cfor (int j = 0; j < 256; j ++) + { + hist[j*programCount*taskCount+i] = g[j]; + } +} + +task void permutation (uniform int span, uniform int n, uniform int64 code[], uniform int pass, uniform int hist[], uniform int64 perm[]) +{ + if (taskIndex >= taskCount) return; + uniform int start = taskIndex*span; + uniform int end = taskIndex == taskCount-1 ? n : start+span; + uniform int strip = (end-start)/programCount; + uniform int tail = (end-start)%programCount; + int i = programCount*taskIndex + programIndex; + int g [256]; + + cfor (int j = 0; j < 256; j ++) + { + g[j] = hist[j*programCount*taskCount+i]; + } + + cfor (int k = start+programIndex*strip; k < start+(programIndex+1)*strip; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + int l = g[c[pass]]; + + perm[l] = code[k]; + + g[c[pass]] = l+1; + } + + if (programIndex == programCount-1) /* remainder is processed by the last lane */ + { + for (int k = start+programCount*strip; k < start+programCount*strip+tail; k ++) + { + unsigned int8 *c = (unsigned int8*) &code[k]; + + int l = g[c[pass]]; + + perm[l] = code[k]; + + g[c[pass]] = l+1; + } + } +} + +task void copy (uniform int span, uniform int n, uniform int64 from[], uniform int64 to[]) +{ + if (taskIndex >= taskCount) return; + uniform int start = taskIndex*span; + uniform int end = taskIndex == taskCount-1 ? n : start+span; + + for (int i = programIndex + start; i < end; i += programCount) + if (i < end) + { + to[i] = from[i]; + } +} + +task void pack (uniform int span, uniform int n, uniform unsigned int code[], uniform int64 pair[]) +{ +#if 0 + if (taskIndex >= taskCount) return; + uniform int start = taskIndex*span; + uniform int end = taskIndex == taskCount-1 ? n : start+span; + + for (int i = programIndex + start; i < end; i += programCount) + if (i < end) + { + pair[i] = ((int64)i<<32)+code[i]; + } +#endif +} + +task void unpack (uniform int span, uniform int n, uniform int64 pair[], uniform int unsigned code[], uniform int order[]) +{ + if (taskIndex >= taskCount) return; + uniform int start = taskIndex*span; + uniform int end = taskIndex == taskCount-1 ? n : start+span; + + for (int i = programIndex + start; i < end; i += programCount) + if (i < end) + { + code[i] = pair[i]; + order[i] = pair[i]>>32; + } +} + +task void addup (uniform int h[], uniform int g[]) +{ + if (taskIndex >= taskCount) return; + uniform int * uniform u = &h[256*programCount*taskIndex]; + uniform int i, x, y = 0; + + for (i = 0; i < 256*programCount; i ++) + { + x = u[i]; + u[i] = y; + y += x; + } + + g[taskIndex] = y; +} + +task void bumpup (uniform int h[], uniform int g[]) +{ + if (taskIndex >= taskCount) return; + uniform int * uniform u = &h[256*programCount*taskIndex]; + uniform int z = g[taskIndex]; + + for (int i = programIndex; i < 256*programCount; i += programCount) + { + u[i] += z; + } +} + +static void prefix_sum (uniform int num, uniform int h[]) +{ + uniform int * uniform g = uniform new uniform int [num+1]; + uniform int i; + + launch[num] addup (h, g+1); + sync; + + for (g[0] = 0, i = 1; i < num; i ++) g[i] += g[i-1]; + + launch[num] bumpup (h, g); + sync; + + delete g; +} + +export void sort_ispc (uniform int n, uniform unsigned int code[], uniform int order[], uniform int ntasks) +{ + uniform int num = ntasks < 1 ? 13*4*8 : ntasks; + uniform int span = n / num; + uniform int hsize = 256*programCount*num; + uniform int * uniform hist = uniform new uniform int [hsize]; + uniform int64 * uniform pair = uniform new uniform int64 [n]; + uniform int64 * uniform temp = uniform new uniform int64 [n]; + uniform int pass, i; + +#if DEBUG + if (n < 100) + { + print ("input: "); + for (i = 0; i < n; i ++) print ("%, ", code[i]); + print ("\n"); + } +#endif + + launch[num] pack (span, n, code, pair); + sync; +#if 0 + + for (pass = 0; pass < 4; pass ++) + { + launch[num] histogram (span, n, pair, pass, hist); + sync; + + prefix_sum (num, hist); + + launch[num] permutation (span, n, pair, pass, hist, temp); + sync; + + launch[num] copy (span, n, temp, pair); + sync; + } + + launch[num] unpack (span, n, pair, code, order); + sync; + +#if DEBUG + for (i = 0; i < n; i ++) + { + if (i > 0 && code[i-1] > code[i]) + print ("ERR at % => % > %; ", i, code[i-1], code[i]); + } + + if (n < 100) + { + print ("output: "); + for (i = 0; i < n; i ++) print ("%, ", code[i]); + print ("\n"); + print ("order: "); + for (i = 0; i < n; i ++) print ("%, ", order[i]); + print ("\n"); + } +#endif +#endif + + delete hist; + delete pair; + delete temp; +} diff --git a/examples_cuda/sort/sort_cu.cpp b/examples_cuda/sort/sort_cu.cpp new file mode 100644 index 00000000..616be83f --- /dev/null +++ b/examples_cuda/sort/sort_cu.cpp @@ -0,0 +1,405 @@ +/* + Copyright (c) 2013, Durham University + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + * Neither the name of Durham University nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/* Author: Tomasz Koziara */ + +#include +#include +#include +#include +#include +#include "../timing.h" +//#include "sort_ispc.h" +//using namespace ispc; + +#include +static inline double rtc(void) +{ + struct timeval Tvalue; + double etime; + struct timezone dummy; + + gettimeofday(&Tvalue,&dummy); + etime = (double) Tvalue.tv_sec + + 1.e-6*((double) Tvalue.tv_usec); + return etime; +} +/******************************/ +#include +#include +#include +#include "drvapi_error_string.h" + +#define checkCudaErrors(err) __checkCudaErrors (err, __FILE__, __LINE__) +// These are the inline versions for all of the SDK helper functions +void __checkCudaErrors(CUresult err, const char *file, const int line) { + if(CUDA_SUCCESS != err) { + std::cerr << "checkCudeErrors() Driver API error = " << err << "\"" + << getCudaDrvErrorString(err) << "\" from file <" << file + << ", line " << line << "\n"; + exit(-1); + } +} + +/**********************/ +/* Basic CUDriver API */ +CUcontext context; + +void createContext(const int deviceId = 0) +{ + CUdevice device; + int devCount; + checkCudaErrors(cuInit(0)); + checkCudaErrors(cuDeviceGetCount(&devCount)); + assert(devCount > 0); + checkCudaErrors(cuDeviceGet(&device, deviceId < devCount ? deviceId : 0)); + + char name[128]; + checkCudaErrors(cuDeviceGetName(name, 128, device)); + std::cout << "Using CUDA Device [0]: " << name << "\n"; + + int devMajor, devMinor; + checkCudaErrors(cuDeviceComputeCapability(&devMajor, &devMinor, device)); + std::cout << "Device Compute Capability: " + << devMajor << "." << devMinor << "\n"; + if (devMajor < 2) { + std::cerr << "ERROR: Device 0 is not SM 2.0 or greater\n"; + exit(1); + } + + // Create driver context + checkCudaErrors(cuCtxCreate(&context, 0, device)); +} +void destroyContext() +{ + checkCudaErrors(cuCtxDestroy(context)); +} + +CUmodule loadModule(const char * module) +{ + const double t0 = rtc(); + CUmodule cudaModule; + // in this branch we use compilation with parameters + + CUlinkState CUState; + CUlinkState *lState = &CUState; + const int nOptions = 7; + CUjit_option options[nOptions]; + void* optionVals[nOptions]; + float walltime; + const unsigned int logSize = 32768; + char error_log[logSize], + info_log[logSize]; + void *cuOut; + size_t outSize; + int myErr = 0; + + // Setup linker options + // Return walltime from JIT compilation + options[0] = CU_JIT_WALL_TIME; + optionVals[0] = (void*) &walltime; + // Pass a buffer for info messages + options[1] = CU_JIT_INFO_LOG_BUFFER; + optionVals[1] = (void*) info_log; + // Pass the size of the info buffer + options[2] = CU_JIT_INFO_LOG_BUFFER_SIZE_BYTES; + optionVals[2] = (void*) logSize; + // Pass a buffer for error message + options[3] = CU_JIT_ERROR_LOG_BUFFER; + optionVals[3] = (void*) error_log; + // Pass the size of the error buffer + options[4] = CU_JIT_ERROR_LOG_BUFFER_SIZE_BYTES; + optionVals[4] = (void*) logSize; + // Make the linker verbose + options[5] = CU_JIT_LOG_VERBOSE; + optionVals[5] = (void*) 1; + // Max # of registers/pthread + options[6] = CU_JIT_MAX_REGISTERS; + int jitRegCount = 32; + optionVals[6] = (void *)(size_t)jitRegCount; + + // Create a pending linker invocation + checkCudaErrors(cuLinkCreate(nOptions,options, optionVals, lState)); + +#if 0 + if (sizeof(void *)==4) + { + // Load the PTX from the string myPtx32 + printf("Loading myPtx32[] program\n"); + // PTX May also be loaded from file, as per below. + myErr = cuLinkAddData(*lState, CU_JIT_INPUT_PTX, (void*)myPtx32, strlen(myPtx32)+1, 0, 0, 0, 0); + } + else +#endif + { + // Load the PTX from the string myPtx (64-bit) + fprintf(stderr, "Loading ptx..\n"); + myErr = cuLinkAddData(*lState, CU_JIT_INPUT_PTX, (void*)module, strlen(module)+1, 0, 0, 0, 0); + myErr = cuLinkAddFile(*lState, CU_JIT_INPUT_LIBRARY, "libcudadevrt.a", 0,0,0); + // PTX May also be loaded from file, as per below. + // myErr = cuLinkAddFile(*lState, CU_JIT_INPUT_PTX, "myPtx64.ptx",0,0,0); + } + + // Complete the linker step + myErr = cuLinkComplete(*lState, &cuOut, &outSize); + + if ( myErr != CUDA_SUCCESS ) + { + // Errors will be put in error_log, per CU_JIT_ERROR_LOG_BUFFER option above. + fprintf(stderr,"PTX Linker Error:\n%s\n",error_log); + assert(0); + } + + // Linker walltime and info_log were requested in options above. + fprintf(stderr, "CUDA Link Completed in %fms [ %g ms]. Linker Output:\n%s\n",walltime,info_log,1e3*(rtc() - t0)); + + // Load resulting cuBin into module + checkCudaErrors(cuModuleLoadData(&cudaModule, cuOut)); + + // Destroy the linker invocation + checkCudaErrors(cuLinkDestroy(*lState)); + fprintf(stderr, " loadModule took %g ms \n", 1e3*(rtc() - t0)); + return cudaModule; +} +void unloadModule(CUmodule &cudaModule) +{ + checkCudaErrors(cuModuleUnload(cudaModule)); +} + +CUfunction getFunction(CUmodule &cudaModule, const char * function) +{ + CUfunction cudaFunction; + checkCudaErrors(cuModuleGetFunction(&cudaFunction, cudaModule, function)); + return cudaFunction; +} + +CUdeviceptr deviceMalloc(const size_t size) +{ + CUdeviceptr d_buf; + checkCudaErrors(cuMemAlloc(&d_buf, size)); + return d_buf; +} +void deviceFree(CUdeviceptr d_buf) +{ + checkCudaErrors(cuMemFree(d_buf)); +} +void memcpyD2H(void * h_buf, CUdeviceptr d_buf, const size_t size) +{ + checkCudaErrors(cuMemcpyDtoH(h_buf, d_buf, size)); +} +void memcpyH2D(CUdeviceptr d_buf, void * h_buf, const size_t size) +{ + checkCudaErrors(cuMemcpyHtoD(d_buf, h_buf, size)); +} +#define deviceLaunch(func,params) \ + checkCudaErrors(cuFuncSetCacheConfig((func), CU_FUNC_CACHE_PREFER_L1)); \ + checkCudaErrors( \ + cuLaunchKernel( \ + (func), \ + 1,1,1, \ + 32, 1, 1, \ + 0, NULL, (params), NULL \ + )); + +typedef CUdeviceptr devicePtr; + + +/**************/ +#include +std::vector readBinary(const char * filename) +{ + std::vector buffer; + FILE *fp = fopen(filename, "rb"); + if (!fp ) + { + fprintf(stderr, "file %s not found\n", filename); + assert(0); + } +#if 0 + char c; + while ((c = fgetc(fp)) != EOF) + buffer.push_back(c); +#else + fseek(fp, 0, SEEK_END); + const unsigned long long size = ftell(fp); /*calc the size needed*/ + fseek(fp, 0, SEEK_SET); + buffer.resize(size); + + if (fp == NULL){ /*ERROR detection if file == empty*/ + fprintf(stderr, "Error: There was an Error reading the file %s \n",filename); + exit(1); + } + else if (fread(&buffer[0], sizeof(char), size, fp) != size){ /* if count of read bytes != calculated size of .bin file -> ERROR*/ + fprintf(stderr, "Error: There was an Error reading the file %s \n", filename); + exit(1); + } +#endif + fprintf(stderr, " read buffer of size= %d bytes \n", (int)buffer.size()); + return buffer; +} + +extern "C" +{ + double CUDALaunch( + void **handlePtr, + const char * func_name, + void **func_args) + { + const std::vector module_str = readBinary("__kernels.ptx"); + const char * module = &module_str[0]; + CUmodule cudaModule = loadModule(module); + CUfunction cudaFunction = getFunction(cudaModule, func_name); + const double t0 = rtc(); + deviceLaunch(cudaFunction, func_args); + checkCudaErrors(cuStreamSynchronize(0)); + const double dt = rtc() - t0; + unloadModule(cudaModule); + return dt; + } +} +/******************************/ + + + +extern void sort_serial (int n, unsigned int code[], int order[]); + +/* progress bar by Ross Hemsley; + * http://www.rosshemsley.co.uk/2011/02/creating-a-progress-bar-in-c-or-any-other-console-app/ */ +static inline void progressbar (unsigned int x, unsigned int n, unsigned int w = 50) +{ + if (n < 100) + { + x *= 100/n; + n = 100; + } + + if ((x != n) && (x % (n/100) != 0)) return; + + using namespace std; + float ratio = x/(float)n; + int c = ratio * w; + + cout << setw(3) << (int)(ratio*100) << "% ["; + for (int x=0; x