Commit 8a205098 authored by Thomas Steinreiter's avatar Thomas Steinreiter
Browse files

removed gsl dependency

parent 44f3618f
......@@ -19,7 +19,6 @@ if (MPI_FOUND AND Boost_FOUND)
include_directories(${MPI_INCLUDE_PATH} ${Boost_INCLUDE_DIRS})
add_executable(${NAME} main.cpp Configuration.cpp Communicator.cpp FileIO.cpp MpiEnvironment.cpp MpiSubarray.cpp MpiWireworld.cpp Tile.cpp Util.cpp)
set(CMAKE_BUILD_TYPE RelWithDebInfo)
add_definitions(-DGSL_UNENFORCED_ON_CONTRACT_VIOLATION)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -ftree-vectorize -flto -Wall -Wextra")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")
......
......@@ -146,17 +146,17 @@ Communicator& Communicator::operator=(Communicator&& other) noexcept {
return *this;
}
void Communicator::Communicate(gsl::multi_span<State, -1, -1>& model) {
void Communicator::Communicate(State* model) {
if (_commDistGraph == MPI_COMM_NULL)
MpiReportErrorAbort("Communicator not initialized");
switch (_commMode) {
case CommunicationMode::Collective:
MPI_Neighbor_alltoallw(model.data(), // sendbuf
MPI_Neighbor_alltoallw(model, // sendbuf
_sizes.data(), // sendcounts
_sendDisplacements.data(), // sdispl
_sendTypes.data(), // sendtypes
model.data(), // recvbuf
model, // recvbuf
_sizes.data(), // recvcounts
_recvDisplacements.data(), // rdispls
_recvTypes.data(), // recvtypes
......@@ -173,19 +173,18 @@ void Communicator::Communicate(gsl::multi_span<State, -1, -1>& model) {
}
}
Communicator::MpiRequest
Communicator::AsyncCommunicate(gsl::multi_span<State, -1, -1>& model) {
Communicator::MpiRequest Communicator::AsyncCommunicate(State* model) {
if (_commDistGraph == MPI_COMM_NULL)
MpiReportErrorAbort("Communicator not initialized");
switch (_commMode) {
case CommunicationMode::Collective: {
MPI_Request req;
MPI_Ineighbor_alltoallw(model.data(), // sendbuf
MPI_Ineighbor_alltoallw(model, // sendbuf
_sizes.data(), // sendcounts
_sendDisplacements.data(), // sdispl
_sendTypes.data(), // sendtypes
model.data(), // recvbuf
model, // recvbuf
_sizes.data(), // recvcounts
_recvDisplacements.data(), // rdispls
_recvTypes.data(), // recvtypes
......@@ -198,25 +197,25 @@ Communicator::AsyncCommunicate(gsl::multi_span<State, -1, -1>& model) {
for (std::size_t i{0}; i < _neighbors.size(); ++i) {
{
MPI_Request req;
MPI_Isend(model.data() + _sendDisplacements[i], // buf
1, // count
_sendTypes[i], // datatype
_neighbors[i], // dest
0, // tag
MPI_COMM_WORLD, // comm
&req); // request
MPI_Isend(model + _sendDisplacements[i], // buf
1, // count
_sendTypes[i], // datatype
_neighbors[i], // dest
0, // tag
MPI_COMM_WORLD, // comm
&req); // request
reqs.push_back(req);
}
{
MPI_Request req;
MPI_Irecv(model.data() + _recvDisplacements[i], // buf
1, // count
_recvTypes[i], // datatype
_neighbors[i], // source
0, // tag
MPI_COMM_WORLD, // comm
&req); // request
MPI_Irecv(model + _recvDisplacements[i], // buf
1, // count
_recvTypes[i], // datatype
_neighbors[i], // source
0, // tag
MPI_COMM_WORLD, // comm
&req); // request
reqs.push_back(req);
}
}
......
#pragma once
#include "gsl/gsl"
#include <boost/container/static_vector.hpp>
#include <mpi.h>
......@@ -64,6 +63,6 @@ class Communicator {
Communicator(Communicator&& other) noexcept;
Communicator& operator=(Communicator&& other) noexcept;
void Communicate(gsl::multi_span<State, -1, -1>& model);
MpiRequest AsyncCommunicate(gsl::multi_span<State, -1, -1>& model);
void Communicate(State* model);
MpiRequest AsyncCommunicate(State* model);
};
\ No newline at end of file
......@@ -3,6 +3,7 @@
#include <algorithm>
#include <fstream>
#include <iomanip>
#include <array>
#include <iostream>
#include <sstream>
......@@ -61,7 +62,7 @@ Size FileIO::GetTileSize(Size globalSize, Size gridSize) {
}
FileIO::Tile::Tile(const std::string& path, HeaderInfo header, Size gridSize,
std::size_t rank, gsl::span<State> buf)
std::size_t rank, State* buf)
: _path(path), _headerLength(header.HeaderLength),
_srcSize(header.GlobalSize), _gridSize(gridSize), _rank(rank), _buf(buf),
_tileSize(FileIO::GetTileSize(header.GlobalSize, gridSize)), //
......@@ -83,7 +84,7 @@ void FileIO::Tile::Read() {
MPI_File_set_view(file, _displ, MPI_CHAR, _tileType.type(), "native",
MPI_INFO_NULL);
MPI_File_read_all(file, _buf.data(), 1, _bufType.type(), MPI_STATUS_IGNORE);
MPI_File_read_all(file, _buf, 1, _bufType.type(), MPI_STATUS_IGNORE);
MPI_File_close(&file);
}
......@@ -94,8 +95,7 @@ void FileIO::Tile::Write() const {
MPI_File_set_view(file, _displ, MPI_CHAR, _tileType.type(), "native",
MPI_INFO_NULL);
MPI_File_write_all(file, _buf.data(), 1, _bufType.type(),
MPI_STATUS_IGNORE);
MPI_File_write_all(file, _buf, 1, _bufType.type(), MPI_STATUS_IGNORE);
/// fix line feeds
// this is done with an collective call, but only the rightmost
......
......@@ -3,8 +3,6 @@
#include <cstddef>
#include <string>
#include "gsl/gsl"
#include "MpiEnvironment.hpp"
#include "MpiSubarray.hpp"
#include "State.hpp"
......@@ -31,7 +29,7 @@ struct FileIO {
const Size _srcSize;
const Size _gridSize;
const std::size_t _rank;
gsl::span<State> _buf;
State* _buf;
const Size _tileSize;
const std::size_t _tileX;
......@@ -42,7 +40,7 @@ struct FileIO {
public:
Tile(const std::string& path, HeaderInfo header, Size gridSize,
std::size_t rank, gsl::span<State> buf);
std::size_t rank, State* buf);
void Read();
void Write() const;
......
......@@ -7,8 +7,6 @@
#include <string>
#include <vector>
#include "gsl/gsl"
#include "FileIO.hpp"
#include "State.hpp"
#include "Tile.hpp"
......@@ -16,10 +14,11 @@
void MpiWireworld::processCell(std::size_t x, std::size_t y) {
const auto& _model = _tile.model();
const auto modelWidth = _tile.modelWidth();
auto& _nextModel = _tile.nextModel();
const auto currentState = _model[y][x];
const auto currentState = _model[y * modelWidth + x];
_nextModel[y][x] = [&]() {
_nextModel[y * modelWidth + x] = [&]() {
switch (currentState) {
case State::ElectronHead:
return State::ElectronTail;
......@@ -28,15 +27,18 @@ void MpiWireworld::processCell(std::size_t x, std::size_t y) {
return State::Conductor;
break;
case State::Conductor: {
const auto idx = [&](std::size_t y, std::size_t x) {
return y * modelWidth + x;
};
const std::array<State, 9> mooreNeighborhood = {
_model[y - 1][x - 1], //
_model[y + 0][x - 1], //
_model[y + 1][x - 1], //
_model[y - 1][x + 0], //
_model[y + 1][x + 0], //
_model[y - 1][x + 1], //
_model[y + 0][x + 1], //
_model[y + 1][x + 1] //
_model[idx(y - 1, x - 1)], //
_model[idx(y + 0, x - 1)], //
_model[idx(y + 1, x - 1)], //
_model[idx(y - 1, x + 0)], //
_model[idx(y + 1, x + 0)], //
_model[idx(y - 1, x + 1)], //
_model[idx(y + 0, x + 1)], //
_model[idx(y + 1, x + 1)] //
};
const auto headCount =
......
#include "Tile.hpp"
#include <iostream>
#include <iterator>
#include <string>
#include <mpi.h>
......@@ -10,7 +11,8 @@
Tile::Tile(const Configuration& cfg, const MpiEnvironment& env)
: _env(env), _cfg(cfg), _header(FileIO::ReadHeader(cfg.InputFilePath)), //
_tileSize(FileIO::GetTileSize(_header.GlobalSize, cfg.Grid)) {
_tileSize(FileIO::GetTileSize(_header.GlobalSize, cfg.Grid)),
_modelWidth(_tileSize.Cols + 2) {
if ((_header.GlobalSize.Cols % _tileSize.Cols) != 0 ||
(_header.GlobalSize.Rows % _tileSize.Rows) != 0) {
MpiReportErrorAbort(
......@@ -19,14 +21,11 @@ Tile::Tile(const Configuration& cfg, const MpiEnvironment& env)
const auto bufsize = (_tileSize.Cols + 2) * (_tileSize.Rows + 2);
_memoryA.resize(bufsize);
_memoryB.resize(bufsize);
_model = gsl::as_multi_span(_memoryA.data(), gsl::dim(_tileSize.Rows + 2),
gsl::dim(_tileSize.Cols + 2));
_nextModel =
gsl::as_multi_span(_memoryB.data(), gsl::dim(_tileSize.Rows + 2),
gsl::dim(_tileSize.Cols + 2));
FileIO::Tile(cfg.InputFilePath, _header, cfg.Grid, _env.worldRank(),
gsl::span<State>(_model))
_model = _memoryA.data();
_nextModel = _memoryB.data();
FileIO::Tile(cfg.InputFilePath, _header, cfg.Grid, _env.worldRank(), _model)
.Read();
}
......@@ -37,9 +36,7 @@ Tile Tile::Read(const Configuration& cfg, const MpiEnvironment& env) {
void Tile::write() const {
const auto& path = _cfg.OutputFilePath;
FileIO::WriteHeader(_header, path, _env);
FileIO::Tile(path, _header, _cfg.Grid, _env.worldRank(),
gsl::span<State>(_model))
.Write();
FileIO::Tile(path, _header, _cfg.Grid, _env.worldRank(), _model).Write();
}
std::ostream& operator<<(std::ostream& out, const Tile& t) {
......@@ -49,10 +46,10 @@ std::ostream& operator<<(std::ostream& out, const Tile& t) {
out << "+\n";
};
hline(out, t.tileSize().Cols);
for (std::size_t x{1}; x <= t.tileSize().Rows; ++x) {
for (std::size_t y{1}; y <= t.tileSize().Rows; ++y) {
out << '|';
for (std::size_t y{1}; y <= t.tileSize().Cols; ++y) {
out << to_integral(t.model()[x][y]);
for (std::size_t x{1}; x <= t.tileSize().Cols; ++x) {
out << to_integral(t.model()[y * t.modelWidth() + x]);
}
out << "|\n";
}
......
......@@ -7,7 +7,6 @@
#include "FileIO.hpp"
#include "MpiEnvironment.hpp"
#include "Util.hpp"
#include "gsl/gsl"
class Tile {
const MpiEnvironment& _env;
......@@ -15,16 +14,18 @@ class Tile {
const HeaderInfo _header;
const Size _tileSize;
const std::size_t _modelWidth;
std::vector<State> _memoryA;
std::vector<State> _memoryB;
gsl::multi_span<State, -1, -1> _model;
gsl::multi_span<State, -1, -1> _nextModel;
State* _model;
State* _nextModel;
Tile(const Configuration& cfg, const MpiEnvironment& env);
public:
auto& model() { return _model; }
auto& model() const { return _model; }
auto& modelWidth() const { return _modelWidth; }
auto& nextModel() { return _nextModel; }
auto tileSize() const { return _tileSize; }
......
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef GSL_GSL_H
#define GSL_GSL_H
#include "gsl_assert" // Ensures/Expects
#include "gsl_util" // finally()/narrow()/narrow_cast()...
#include "multi_span" // multi_span, strided_span...
#include "span" // span
#include "string_span" // zstring, string_span, zstring_builder...
#include <memory>
#ifdef _MSC_VER
// No MSVC does constexpr fully yet
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
// MSVC 2013 workarounds
#if _MSC_VER <= 1800
// noexcept is not understood
#pragma push_macro("noexcept")
#define noexcept /*noexcept*/
// turn off some misguided warnings
#pragma warning(push)
#pragma warning(disable : 4351) // warns about newly introduced aggregate initializer behavior
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
namespace gsl
{
//
// GSL.owner: ownership pointers
//
using std::unique_ptr;
using std::shared_ptr;
template <class T>
using owner = T;
//
// not_null
//
// Restricts a pointer or smart pointer to only hold non-null values.
//
// Has zero size overhead over T.
//
// If T is a pointer (i.e. T == U*) then
// - allow construction from U* or U&
// - disallow construction from nullptr_t
// - disallow default construction
// - ensure construction from U* fails with nullptr
// - allow implicit conversion to U*
//
template <class T>
class not_null
{
static_assert(std::is_assignable<T&, std::nullptr_t>::value, "T cannot be assigned nullptr.");
public:
not_null(T t) : ptr_(t) { ensure_invariant(); }
not_null& operator=(const T& t)
{
ptr_ = t;
ensure_invariant();
return *this;
}
not_null(const not_null& other) = default;
not_null& operator=(const not_null& other) = default;
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null(const not_null<U>& other)
{
*this = other;
}
template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null& operator=(const not_null<U>& other)
{
ptr_ = other.get();
return *this;
}
// prevents compilation when someone attempts to assign a nullptr
not_null(std::nullptr_t) = delete;
not_null(int) = delete;
not_null<T>& operator=(std::nullptr_t) = delete;
not_null<T>& operator=(int) = delete;
T get() const
{
#ifdef _MSC_VER
__assume(ptr_ != nullptr);
#endif
return ptr_;
} // the assume() should help the optimizer
operator T() const { return get(); }
T operator->() const { return get(); }
bool operator==(const T& rhs) const { return ptr_ == rhs; }
bool operator!=(const T& rhs) const { return !(*this == rhs); }
private:
T ptr_;
// we assume that the compiler can hoist/prove away most of the checks inlined from this
// function
// if not, we could make them optional via conditional compilation
void ensure_invariant() const { Expects(ptr_ != nullptr); }
// unwanted operators...pointers only point to single objects!
// TODO ensure all arithmetic ops on this type are unavailable
not_null<T>& operator++() = delete;
not_null<T>& operator--() = delete;
not_null<T> operator++(int) = delete;
not_null<T> operator--(int) = delete;
not_null<T>& operator+(size_t) = delete;
not_null<T>& operator+=(size_t) = delete;
not_null<T>& operator-(size_t) = delete;
not_null<T>& operator-=(size_t) = delete;
};
} // namespace gsl
namespace std
{
template <class T>
struct hash<gsl::not_null<T>>
{
size_t operator()(const gsl::not_null<T>& value) const { return hash<T>{}(value); }
};
} // namespace std
#ifdef _MSC_VER
#undef constexpr
#pragma pop_macro("constexpr")
#if _MSC_VER <= 1800
#undef noexcept
#pragma pop_macro("noexcept")
#pragma warning(pop)
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
#endif // GSL_GSL_H
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef GSL_CONTRACTS_H
#define GSL_CONTRACTS_H
#include <exception>
#include <stdexcept>
//
// There are three configuration options for this GSL implementation's behavior
// when pre/post conditions on the GSL types are violated:
//
// 1. GSL_TERMINATE_ON_CONTRACT_VIOLATION: std::terminate will be called (default)
// 2. GSL_THROW_ON_CONTRACT_VIOLATION: a gsl::fail_fast exception will be thrown
// 3. GSL_UNENFORCED_ON_CONTRACT_VIOLATION: nothing happens
//
#if !(defined(GSL_THROW_ON_CONTRACT_VIOLATION) ^ defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION) ^ \
defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION))
#define GSL_TERMINATE_ON_CONTRACT_VIOLATION
#endif
#define GSL_STRINGIFY_DETAIL(x) #x
#define GSL_STRINGIFY(x) GSL_STRINGIFY_DETAIL(x)
//
// GSL.assert: assertions
//
namespace gsl
{
struct fail_fast : public std::runtime_error
{
explicit fail_fast(char const* const message) : std::runtime_error(message) {}
};
}
#if defined(GSL_THROW_ON_CONTRACT_VIOLATION)
#define Expects(cond) \
if (!(cond)) \
throw gsl::fail_fast("GSL: Precondition failure at " __FILE__ ": " GSL_STRINGIFY(__LINE__));
#define Ensures(cond) \
if (!(cond)) \
throw gsl::fail_fast("GSL: Postcondition failure at " __FILE__ \
": " GSL_STRINGIFY(__LINE__));
#elif defined(GSL_TERMINATE_ON_CONTRACT_VIOLATION)
#define Expects(cond) \
if (!(cond)) std::terminate();
#define Ensures(cond) \
if (!(cond)) std::terminate();
#elif defined(GSL_UNENFORCED_ON_CONTRACT_VIOLATION)
#define Expects(cond)
#define Ensures(cond)
#endif
#endif // GSL_CONTRACTS_H
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) 2015 Microsoft Corporation. All rights reserved.
//
// This code is licensed under the MIT License (MIT).
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
///////////////////////////////////////////////////////////////////////////////
#pragma once
#ifndef GSL_BYTE_H
#define GSL_BYTE_H
#ifdef _MSC_VER
// MSVC 2013 workarounds
#if _MSC_VER <= 1800
// constexpr is not understood
#pragma push_macro("constexpr")
#define constexpr /*constexpr*/
// noexcept is not understood
#pragma push_macro("noexcept")
#define noexcept /*noexcept*/
#endif // _MSC_VER <= 1800
#endif // _MSC_VER
namespace gsl
{