Program Listing for File gmt_utility.h

Return to documentation for file (include/shad/runtime/mappings/gmt/gmt_utility.h)

//===------------------------------------------------------------*- C++ -*-===//
//
//                                     SHAD
//
//      The Scalable High-performance Algorithms and Data Structure Library
//
//===----------------------------------------------------------------------===//
//
// Copyright 2018 Battelle Memorial Institute
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy
// of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.
//
//===----------------------------------------------------------------------===//

#ifndef INCLUDE_SHAD_RUNTIME_MAPPINGS_GMT_GMT_UTILITY_H_
#define INCLUDE_SHAD_RUNTIME_MAPPINGS_GMT_GMT_UTILITY_H_

#include <cstddef>
#include <cstdint>
#include <sstream>
#include <system_error>

#include "shad/runtime/locality.h"

namespace shad {
namespace rt {

namespace impl {

static uint32_t kOverSubscriptionFactor = 300;

inline uint32_t getNodeId(const Locality &loc) {
  return static_cast<uint32_t>(loc);
}

inline void checkLocality(const Locality &loc) {
  uint32_t nodeID = getNodeId(loc);
  if (nodeID >= gmt_num_nodes()) {
    std::stringstream ss;
    ss << "The system does not include " << loc;
    throw std::system_error(0xdeadc0de, std::generic_category(), ss.str());
  }
}

inline void checkInputSize(size_t size) {
  if (size > gmt_max_args_per_task()) {
    std::stringstream ss;
    ss << "The input size exeeds the hard limit of " << gmt_max_args_per_task()
       << "B imposed by GMT.  A more general solution is under development.";
    throw std::system_error(0xdeadc0de, std::generic_category(), ss.str());
  }
}

inline void checkOutputSize(size_t size) {
  if (size > gmt_max_return_size()) {
    std::stringstream ss;
    ss << "The output size exeeds the hard limit of " << gmt_max_return_size()
       << "B imposed by GMT.  A more general solution is under development.";
    throw std::system_error(0xdeadc0de, std::generic_category(), ss.str());
  }
}

template <typename FunT, typename InArgsT>
struct ExecFunWrapperArgs {
  FunT fun;
  InArgsT args;
};

template <typename FunT, typename InArgsT>
void execFunWrapper(const void *args, uint32_t args_size, void *, uint32_t *,
                    gmt_handle_t) {
  const ExecFunWrapperArgs<FunT, InArgsT> &funArgs =
      *reinterpret_cast<const ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  funArgs.fun(funArgs.args);
}

inline void execFunWrapper(const void *args, uint32_t args_size, void *,
                           uint32_t *, gmt_handle_t) {
  using FunctionTy = void (*)(const uint8_t *, const uint32_t);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));
  functionPtr(reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr),
              args_size - sizeof(functionPtr));
}

template <typename FunT, typename InArgsT>
void execFunWithRetBuffWrapper(const void *args, uint32_t, void *result,
                               uint32_t *resultSize, gmt_handle_t) {
  const impl::ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const impl::ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;
  funArgs->fun(fnargs, reinterpret_cast<uint8_t *>(result), resultSize);

  checkOutputSize(*resultSize);
}

inline void execFunWithRetBuffWrapper(const void *args, uint32_t argsSize,
                                      void *result, uint32_t *resultSize,
                                      gmt_handle_t) {
  using FunctionTy =
      void (*)(const uint8_t *, const uint32_t, uint8_t *, uint32_t *);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));
  functionPtr(reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr),
              argsSize - sizeof(functionPtr),
              reinterpret_cast<uint8_t *>(result), resultSize);

  checkOutputSize(*resultSize);
}

template <typename FunT, typename InArgsT, typename ResT>
void execFunWithRetWrapper(const void *args, uint32_t args_size, void *result,
                           uint32_t *resSize, gmt_handle_t) {
  using FunctionTy = void (*)(const InArgsT &, ResT *);

  const impl::ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const impl::ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;

  funArgs->fun(fnargs, reinterpret_cast<ResT *>(result));
  *resSize = sizeof(ResT);
}

template <typename ResT>
void execFunWithRetWrapper(const void *args, uint32_t args_size, void *result,
                           uint32_t *resSize, gmt_handle_t) {
  using FunctionTy = void (*)(const uint8_t *, const uint32_t, ResT *);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));

  ResT *resultPtr = reinterpret_cast<ResT *>(result);

  functionPtr(reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr),
              args_size - sizeof(functionPtr), resultPtr);
  *resSize = sizeof(ResT);
}

inline void forEachWrapper(uint64_t startIt, uint64_t numIters,
                           const void *args, gmt_handle_t) {
  using FunctionTy = void (*)(const uint8_t *, const uint32_t, size_t);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));
  const uint32_t argSize = *reinterpret_cast<const uint32_t *>(
      reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr));

  const uint8_t *buffer = reinterpret_cast<const uint8_t *>(args) +
                          sizeof(functionPtr) + sizeof(argSize);

  for (size_t i = 0; i < numIters; ++i)
    functionPtr(buffer, argSize, startIt + i);
}

template <typename FunT, typename InArgsT>
void forEachWrapper(uint64_t startIt, uint64_t numIters, const void *args,
                    gmt_handle_t) {
  const impl::ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const impl::ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;

  for (size_t i = 0; i < numIters; ++i) funArgs->fun(fnargs, startIt + i);
}

static uint32_t garbageSize;

inline gmt_handle_t getGmtHandle(Handle &handle) {
  return static_cast<uint64_t>(handle);
}

template <typename FunT, typename InArgsT>
void execAsyncFunWrapper(const void *args, uint32_t args_size, void *,
                         uint32_t *, gmt_handle_t handle) {
  const ExecFunWrapperArgs<FunT, InArgsT> &funArgs =
      *reinterpret_cast<const ExecFunWrapperArgs<FunT, InArgsT> *>(args);

  Handle H(handle);
  funArgs.fun(H, funArgs.args);
}

inline void execAsyncFunWrapper(const void *args, uint32_t args_size, void *,
                                uint32_t *, gmt_handle_t handle) {
  using FunctionTy = void (*)(Handle &, const uint8_t *, const uint32_t);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));

  Handle H(handle);
  functionPtr(H, reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr),
              args_size - sizeof(functionPtr));
}

template <typename FunT, typename InArgsT, typename ResT>
void asyncExecFunWithRetWrapper(const void *args, uint32_t args_size,
                                void *result, uint32_t *resSize,
                                gmt_handle_t handle) {
  using FunctionTy = void (*)(Handle &, const InArgsT &, ResT *);

  const ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;

  Handle H(handle);
  funArgs->fun(H, fnargs, reinterpret_cast<ResT *>(result));
  *resSize = sizeof(ResT);
}

template <typename ResT>
void asyncExecFunWithRetWrapper(const void *args, uint32_t args_size,
                                void *result, uint32_t *resSize,
                                gmt_handle_t handle) {
  using FunctionTy =
      void (*)(Handle &, const uint8_t *, const uint32_t, ResT *);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));

  ResT *resultPtr = reinterpret_cast<ResT *>(result);

  Handle H(handle);
  functionPtr(H, reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr),
              args_size - sizeof(functionPtr), resultPtr);
  *resSize = sizeof(ResT);
}

template <typename FunT, typename InArgsT>
void asyncExecFunWithRetBuffWrapper(const void *args, uint32_t, void *result,
                                    uint32_t *resultSize, gmt_handle_t handle) {
  const ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;

  Handle H(handle);
  funArgs->fun(H, fnargs, reinterpret_cast<uint8_t *>(result), resultSize);

  checkOutputSize(*resultSize);
}

inline void asyncExecFunWithRetBuffWrapper(const void *args, uint32_t argsSize,
                                           void *result, uint32_t *resultSize,
                                           gmt_handle_t handle) {
  using FunctionTy = void (*)(Handle &, const uint8_t *, const uint32_t,
                              uint8_t *, uint32_t *);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));

  Handle H(handle);
  functionPtr(H, reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr),
              argsSize - sizeof(functionPtr),
              reinterpret_cast<uint8_t *>(result), resultSize);

  checkOutputSize(*resultSize);
}

inline void asyncForEachWrapper(uint64_t startIt, uint64_t numIters,
                                const void *args, gmt_handle_t handle) {
  using FunctionTy =
      void (*)(Handle &, const uint8_t *, const uint32_t, size_t);

  FunctionTy functionPtr =
      *reinterpret_cast<FunctionTy *>(const_cast<void *>(args));
  const uint32_t argSize = *reinterpret_cast<const uint32_t *>(
      reinterpret_cast<const uint8_t *>(args) + sizeof(functionPtr));

  const uint8_t *buffer = reinterpret_cast<const uint8_t *>(args) +
                          sizeof(functionPtr) + sizeof(argSize);
  Handle H(handle);
  for (size_t i = 0; i < numIters; ++i)
    functionPtr(H, buffer, argSize, startIt + i);
}

template <typename FunT, typename InArgsT>
void asyncForEachWrapper(uint64_t startIt, uint64_t numIters, const void *args,
                         gmt_handle_t handle) {
  const ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;

  Handle H(handle);
  for (size_t i = 0; i < numIters; ++i) funArgs->fun(H, fnargs, startIt + i);
}

template <typename FunT, typename InArgsT>
void execAsyncFunWithRetBuffWrapper(const void *args, uint32_t args_size,
                                    void *result, uint32_t *resSize,
                                    gmt_handle_t handle) {
  const ExecFunWrapperArgs<FunT, InArgsT> *funArgs =
      reinterpret_cast<const ExecFunWrapperArgs<FunT, InArgsT> *>(args);
  const InArgsT &fnargs = funArgs->args;
  funArgs->fun(fnargs, reinterpret_cast<uint8_t *>(result), resSize,
               Handle(handle));

  checkOutputSize(*resSize);
}

}  // namespace impl

}  // namespace rt
}  // namespace shad

#endif  // INCLUDE_SHAD_RUNTIME_MAPPINGS_GMT_GMT_UTILITY_H_