diff --git a/CMakeLists.txt b/CMakeLists.txt index 27736b6b..c074075c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ endif () include(cmake/register_models.cmake) # register out models +register_model(serial SERIAL SerialStream.cpp) register_model(omp OMP OMPStream.cpp) register_model(ocl OCL OCLStream.cpp) register_model(std-data STD_DATA STDDataStream.cpp) diff --git a/src/ci-test-compile.sh b/src/ci-test-compile.sh index 249bab4f..57b89afb 100755 --- a/src/ci-test-compile.sh +++ b/src/ci-test-compile.sh @@ -138,6 +138,7 @@ build_gcc() { local name="gcc_build" local cxx="-DCMAKE_CXX_COMPILER=${GCC_CXX:?}" + run_build $name "${GCC_CXX:?}" serial "$cxx" run_build $name "${GCC_CXX:?}" omp "$cxx" if [ "$MODEL" = "all" ] || [ "$MODEL" = "OMP" ]; then # sanity check that it at least runs @@ -219,6 +220,7 @@ build_gcc() { build_clang() { local name="clang_build" local cxx="-DCMAKE_CXX_COMPILER=${CLANG_CXX:?}" + run_build $name "${CLANG_CXX:?}" serial "$cxx" run_build $name "${CLANG_CXX:?}" omp "$cxx" if [ "${CLANG_OMP_OFFLOAD_AMD:-false}" != "false" ]; then @@ -276,6 +278,7 @@ build_nvhpc() { } build_aocc() { + run_build aocc_build "${AOCC_CXX:?}" serial "-DCMAKE_CXX_COMPILER=${AOCC_CXX:?}" run_build aocc_build "${AOCC_CXX:?}" omp "-DCMAKE_CXX_COMPILER=${AOCC_CXX:?}" } @@ -309,6 +312,7 @@ build_icpc() { set -u local name="intel_build" local cxx="-DCMAKE_CXX_COMPILER=${ICPC_CXX:?}" + run_build $name "${ICPC_CXX:?}" serial "$cxx" run_build $name "${ICPC_CXX:?}" omp "$cxx" run_build $name "${ICPC_CXX:?}" ocl "$cxx -DOpenCL_LIBRARY=${OCL_LIB:?}" if check_cmake_ver "3.20.0"; then diff --git a/src/main.cpp b/src/main.cpp index abfc14e4..5b53a5d8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -49,6 +49,8 @@ #include "SYCLStream2020.h" #elif defined(OMP) #include "OMPStream.h" +#elif defined(SERIAL) +#include "SerialStream.h" #elif defined(FUTHARK) #include "FutharkStream.h" #endif @@ -300,6 +302,10 @@ void run() // Use the OpenMP implementation stream = new OMPStream(ARRAY_SIZE, deviceIndex); +#elif defined(SERIAL) + // Use the Serial implementation + stream = new SerialStream(ARRAY_SIZE, deviceIndex); + #elif defined(FUTHARK) // Use the Futhark implementation stream = new FutharkStream(ARRAY_SIZE, deviceIndex); diff --git a/src/serial/SerialStream.cpp b/src/serial/SerialStream.cpp new file mode 100644 index 00000000..807e6dbd --- /dev/null +++ b/src/serial/SerialStream.cpp @@ -0,0 +1,134 @@ + +// Copyright (c) 2015-16 Tom Deakin, Simon McIntosh-Smith, Tom Lin +// University of Bristol HPC +// +// For full license terms please see the LICENSE file distributed with this +// source code + +#include // For aligned_alloc +#include "SerialStream.h" + +#ifndef ALIGNMENT +#define ALIGNMENT (2*1024*1024) // 2MB +#endif + +template +SerialStream::SerialStream(const int ARRAY_SIZE, int device) +{ + array_size = ARRAY_SIZE; + + // Allocate on the host + this->a = (T*)aligned_alloc(ALIGNMENT, sizeof(T)*array_size); + this->b = (T*)aligned_alloc(ALIGNMENT, sizeof(T)*array_size); + this->c = (T*)aligned_alloc(ALIGNMENT, sizeof(T)*array_size); +} + +template +SerialStream::~SerialStream() +{ + free(a); + free(b); + free(c); +} + +template +void SerialStream::init_arrays(T initA, T initB, T initC) +{ + int array_size = this->array_size; + for (int i = 0; i < array_size; i++) + { + a[i] = initA; + b[i] = initB; + c[i] = initC; + } +} + +template +void SerialStream::read_arrays(std::vector& h_a, std::vector& h_b, std::vector& h_c) +{ + for (int i = 0; i < array_size; i++) + { + h_a[i] = a[i]; + h_b[i] = b[i]; + h_c[i] = c[i]; + } + +} + +template +void SerialStream::copy() +{ + for (int i = 0; i < array_size; i++) + { + c[i] = a[i]; + } +} + +template +void SerialStream::mul() +{ + const T scalar = startScalar; + for (int i = 0; i < array_size; i++) + { + b[i] = scalar * c[i]; + } +} + +template +void SerialStream::add() +{ + for (int i = 0; i < array_size; i++) + { + c[i] = a[i] + b[i]; + } +} + +template +void SerialStream::triad() +{ + const T scalar = startScalar; + for (int i = 0; i < array_size; i++) + { + a[i] = b[i] + scalar * c[i]; + } +} + +template +void SerialStream::nstream() +{ + const T scalar = startScalar; + for (int i = 0; i < array_size; i++) + { + a[i] += b[i] + scalar * c[i]; + } +} + +template +T SerialStream::dot() +{ + T sum{}; + for (int i = 0; i < array_size; i++) + { + sum += a[i] * b[i]; + } + return sum; +} + + + +void listDevices(void) +{ + std::cout << "0: CPU" << std::endl; +} + +std::string getDeviceName(const int) +{ + return std::string("Device name unavailable"); +} + +std::string getDeviceDriver(const int) +{ + return std::string("Device driver unavailable"); +} +template class SerialStream; +template class SerialStream; diff --git a/src/serial/SerialStream.h b/src/serial/SerialStream.h new file mode 100644 index 00000000..d974fe99 --- /dev/null +++ b/src/serial/SerialStream.h @@ -0,0 +1,43 @@ + +// Copyright (c) 2015-16 Tom Deakin, Simon McIntosh-Smith, Tom Lin +// University of Bristol HPC +// +// For full license terms please see the LICENSE file distributed with this +// source code + +#pragma once + +#include +#include + +#include "Stream.h" + + +#define IMPLEMENTATION_STRING "Serial" + +template +class SerialStream : public Stream +{ + protected: + // Size of arrays + int array_size; + + // Device side pointers + T *a; + T *b; + T *c; + + public: + SerialStream(const int, int); + ~SerialStream(); + + virtual void copy() override; + virtual void add() override; + virtual void mul() override; + virtual void triad() override; + virtual void nstream() override; + virtual T dot() override; + + virtual void init_arrays(T initA, T initB, T initC) override; + virtual void read_arrays(std::vector& a, std::vector& b, std::vector& c) override; +}; diff --git a/src/serial/model.cmake b/src/serial/model.cmake new file mode 100644 index 00000000..d1818466 --- /dev/null +++ b/src/serial/model.cmake @@ -0,0 +1,4 @@ +macro(setup) + # Nothing to do +endmacro() +