Skip to content

Commit

Permalink
initial HIP improvements, scope::system
Browse files Browse the repository at this point in the history
  • Loading branch information
cwpearson committed Nov 3, 2022
1 parent f8b5edc commit cb67568
Show file tree
Hide file tree
Showing 12 changed files with 296 additions and 2 deletions.
Empty file added .clang-format
Empty file.
5 changes: 4 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/modules ${CMAKE_MODULE_PATH})
option(SCOPE_USE_NUMA ON)
option(SCOPE_USE_NVTX ON)
option(SCOPE_USE_OPENMP ON)
option(SCOPE_USE_CUDA ON)
option(SCOPE_USE_CUDA OFF)
option(SCOPE_USE_HIP ON)

# link libraries but make the includes system includes to suppress warnings
# https://stackoverflow.com/questions/52135983/cmake-target-link-libraries-include-as-system-to-suppress-compiler-warnings
Expand Down Expand Up @@ -48,6 +49,8 @@ add_library(scope
${SCOPE_SOURCES}
)

add_subdirectory(bin)

# if we are included in another project with add_subdirectory(), mark our includes as system includes
if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
target_include_directories(scope PUBLIC
Expand Down
3 changes: 3 additions & 0 deletions bin/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

add_executable(system-graph system-graph.cpp)
target_link_libraries(system-graph scope)
29 changes: 29 additions & 0 deletions bin/system-graph.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#include <iostream>

#include "scope/system.hpp"
#include "scope/init.hpp"

int main(int argc, char **argv) {

using TransferMethod = scope::system::TransferMethod;

scope::initialize(&argc, argv);

std::vector<MemorySpace> spaces = scope::system::memory_spaces();

for (const auto &space : spaces) {
std::cout << space << "\n";
}

for (size_t i = 0; i < spaces.size(); ++i) {
for (size_t j = 0; j < spaces.size(); ++j) {
std::cout << spaces[i] << " -> " << spaces[j] << "\n";
std::vector<TransferMethod> methods = scope::system::transfer_methods(spaces[i], spaces[j]);
for (const auto &method : methods) {
std::cout << "\t" << method << "\n";
}
}
}


}
7 changes: 7 additions & 0 deletions docs/rzvernal.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```
cmake .. -DCMAKE_CXX_COMPILER=hipcc
```

```
```
19 changes: 19 additions & 0 deletions include/scope/hip.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#pragma once

#include <sstream>

#include <hip/hip_runtime.h>

namespace scope {
namespace detail {
inline void success_or_throw(hipError_t err, const char *file, int line) {
if (hipSuccess != err) {
std::stringstream ss;
ss << __FILE__ << ":" << __LINE__ << "HIP error " << hipGetErrorString(err);
throw std::runtime_error(ss.str());
}
}
}
}

#define HIP_RUNTIME(x) scope::detail::success_or_throw(x, __FILE__, __LINE__)
69 changes: 69 additions & 0 deletions include/scope/memory_space.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#pragma once

#include <ostream>

class MemorySpace {
public:
enum class Kind {
numa
,hip_device
,hip_managed
,cuda_device
};

static MemorySpace numa_space(int id) {
MemorySpace ms;
ms.kind_ = Kind::numa;
ms.numaId_ = id;
return ms;
}

#ifdef __HIP__
static MemorySpace hip_device_space(int id) {
MemorySpace ms;
ms.kind_ = Kind::hip_device;
ms.deviceId_ = id;
return ms;
}
static MemorySpace hip_managed_space() {
MemorySpace ms;
ms.kind_ = Kind::hip_managed;
return ms;
}
#endif // __HIP__

const Kind &kind() const noexcept {return kind_;}

friend std::ostream& operator<<(std::ostream& os, const MemorySpace& ms);

private:
Kind kind_;
int deviceId_;
int numaId_;
};


inline std::ostream& operator<<(std::ostream& os, const MemorySpace& ms)
{
using Kind = MemorySpace::Kind;

switch(ms.kind_) {
case Kind::numa: {
os << "numa:" << ms.numaId_;
break;
}
case Kind::hip_device: {
os << "hip_device:" << ms.deviceId_;
break;
}
case Kind::hip_managed: {
os << "hip_managed";
break;
}
case Kind::cuda_device: {
os << "cuda_device:" << ms.deviceId_;
break;
}
}
return os;
}
5 changes: 5 additions & 0 deletions include/scope/numa.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ If no NUMA support, return 1
*/
int node_count();

/* return the numa nodes on the system
*/
const std::vector<int> &nodes();

/* return the NUMA ids that contain CPUs on the system
*/
const std::vector<int> &ids();
Expand All @@ -37,6 +41,7 @@ std::vector<int> cpus_in_node(int node);
*/
std::vector<int> cpus_in_nodes(const std::vector<int> &nodes);


/* bind to `node` while in scope. Release bind on destruction
*/
class ScopedBind {
Expand Down
129 changes: 129 additions & 0 deletions include/scope/system.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
#pragma once

#include <vector>

#include "scope/memory_space.hpp"
#include "scope/numa.hpp"

#ifdef __HIP__
#include "scope/hip.hpp"
#endif

namespace scope {
namespace system {

inline std::vector<MemorySpace> hip_memory_spaces() {
int ndev;
HIP_RUNTIME(hipGetDeviceCount(&ndev));

std::vector<MemorySpace> ret;

for (int i = 0; i < ndev; ++i) {
ret.push_back(MemorySpace::hip_device_space(i));
}
ret.push_back(MemorySpace::hip_managed_space());
return ret;
}

inline std::vector<MemorySpace> numa_memory_spaces() {

auto nodes = numa::nodes();

std::vector<MemorySpace> ret;
for (const auto &node : nodes) {
ret.push_back(MemorySpace::numa_space(node));
}

return ret;
}


std::vector<MemorySpace> memory_spaces() {

std::vector<MemorySpace> spaces;

auto numaSpaces = numa_memory_spaces();
spaces.insert(spaces.begin(), numaSpaces.begin(), numaSpaces.end());

#ifdef __HIP__
auto hipSpaces = hip_memory_spaces();
spaces.insert(spaces.begin(), hipSpaces.begin(), hipSpaces.end());
#endif

return spaces;

};

enum class TransferMethod {
hip_memcpy,
hip_memcpy_async,
};

std::vector<TransferMethod> transfer_methods(const MemorySpace &src, const MemorySpace &dst) {

using Kind = MemorySpace::Kind;

switch(src.kind()) {
case Kind::hip_device: {
switch(dst.kind()) {
case Kind::hip_device:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::hip_managed:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::numa:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::cuda_device:
return {};
}
}
case Kind::hip_managed: {
switch(dst.kind()) {
case Kind::hip_device:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::hip_managed:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::numa:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::cuda_device:
throw std::runtime_error("unimplemented");
}
}
case Kind::numa: {
switch(dst.kind()) {
case Kind::hip_device:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::hip_managed:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::numa:
return {TransferMethod::hip_memcpy, TransferMethod::hip_memcpy_async};
case Kind::cuda_device:
throw std::runtime_error("unimplemented");
}
}
case Kind::cuda_device: {
throw std::runtime_error("unimplemented");
}
}

return {};
}

} // namespace system
} // namespace scope

std::ostream& operator<<(std::ostream& os, const scope::system::TransferMethod& tm)
{
using TransferMethod = scope::system::TransferMethod;

switch(tm) {
case TransferMethod::hip_memcpy: {
os << "hipMemcpy";
break;
}
case TransferMethod::hip_memcpy_async: {
os << "hipMemcpyAsync";
break;
}
}
return os;
}
15 changes: 15 additions & 0 deletions load-env.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash

echo_and_do() {
echo "$@"
"$@"
}

if [[ $(hostname) =~ rzvernal ]]; then

echo_and_do module load cmake/3.24.2
echo_and_do module load rocm/5.2.0

else
echo "UNRECOGNIZED PLATFORM $(hostname)"
fi
Empty file added src/hip.cpp
Empty file.
17 changes: 16 additions & 1 deletion src/numa.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <map>
#include <set>
#include <thread>
#include <iostream>

#if SCOPE_USE_NUMA
#include <numa.h>
Expand All @@ -25,20 +26,32 @@ namespace detail {
/* cache of node -> cpus
*/
std::map<int, std::vector<int>> CPUsInNode;

/* cache of node -> memory */
std::map<int, std::vector<int>> memoriesInNode;

/* all nodes with CPUs
*/
std::vector<int> nodesWithCPUs;

std::vector<int> nodes;

} // namespace detail

void init() {

/* cache which nodes have CPUs
*/
#if SCOPE_USE_NUMA

for (int i = 0; i < numa_max_possible_node(); ++i) {
if (numa_bitmask_isbitset(numa_all_nodes_ptr, i)) {
detail::nodes.push_back(i);
}
}

for (int i = 0; i < numa_num_configured_cpus(); ++i) {
int node = numa_node_of_cpu(i);

if (scope::flags::visibleNUMAs.empty() ||
(scope::flags::visibleNUMAs.end() !=
std::find(scope::flags::visibleNUMAs.begin(),
Expand Down Expand Up @@ -120,6 +133,8 @@ const std::vector<int> &ids() { return detail::nodesWithCPUs; }

const std::vector<int> &cpu_nodes() { return ids(); }

const std::vector<int> &nodes() {return detail::nodes; }

std::vector<int> cpus_in_node(int node) {
if (detail::CPUsInNode.count(node)) {
return detail::CPUsInNode[node];
Expand Down

0 comments on commit cb67568

Please sign in to comment.