Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implemented Memory Provider for Heterogeneous memory. #674

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 9 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,13 @@ else()
endif()
endif()

option(ENABLE_MEMKIND "Use Memkind library for heterogeneous memory" OFF)
if(ENABLE_MEMKIND)
set(MEMKIND_REQUIRED_VERSION 1.11.0)
find_package(PkgConfig QUIET)
pkg_check_modules(memkind REQUIRED memkind>=${MEMKIND_REQUIRED_VERSION})
endif()

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

if(MSVC)
Expand Down Expand Up @@ -830,11 +837,11 @@ add_custom_target(rerun_cmake ALL
)
add_dependencies(omnisci_server rerun_cmake)

target_link_libraries(omnisci_server mapd_thrift thrift_handler ${MAPD_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS} ${CUDA_LIBRARIES} ${PROFILER_LIBS} ${ZLIB_LIBRARIES} ${LOCALE_LINK_FLAG})
target_link_libraries(omnisci_server mapd_thrift thrift_handler ${MAPD_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS} ${CUDA_LIBRARIES} ${PROFILER_LIBS} ${ZLIB_LIBRARIES} ${LOCALE_LINK_FLAG} ${memkind_LIBRARIES})

target_link_libraries(initdb mapd_thrift thrift_handler ${MAPD_LIBRARIES} ${Boost_LIBRARIES} ${CMAKE_DL_LIBS}
${CUDA_LIBRARIES} ${PROFILER_LIBS} ${ZLIB_LIBRARIES} ${BLOSC_LIBRARIES}
${LOCALE_LINK_FLAG})
${LOCALE_LINK_FLAG} ${memkind_LIBRARIES})

macro(set_dpkg_arch arch_in arch_out)
if("${arch_in}" STREQUAL "x86_64")
Expand Down
156 changes: 156 additions & 0 deletions DataMgr/Allocators/HeteroMem/MemResourceProvider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// SPDX-License-Identifier: BSD-2-Clause
/* Copyright (C) 2020 Intel Corporation. */

#include "DataMgr/Allocators/HeteroMem/MemResourceProvider.h"

#include "Logger/Logger.h"

// MemKind Allocator
#include "DataMgr/Allocators/HeteroMem/MemResources/memory_resources.h"

#include <memory>

#include <unistd.h>
#include <cstdint>
#include <filesystem>
#include "memkind.h"

#ifdef __APPLE__
#include <sys/sysctl.h>
#include <sys/types.h>
#endif

namespace Buffer_Namespace {
using pmem_memory_resource_type = libmemkind::pmem::memory_resource;
using static_kind_memory_resource_type = libmemkind::static_kind::memory_resource;

MemoryResourceProvider::MemoryResourceProvider()
: dram_mem_resource_(new static_kind_memory_resource_type(libmemkind::kinds::REGULAR))
, mem_resources_(3, dram_mem_resource_.get()) {
if (memkind_check_available(MEMKIND_DAX_KMEM_ALL) == MEMKIND_SUCCESS) {
pmem_mem_resource_ = std::make_unique<static_kind_memory_resource_type>(
libmemkind::kinds::DAX_KMEM_ALL);
mem_resources_[CAPACITY] = pmem_mem_resource_.get();
CHECK(mem_resources_[CAPACITY]);
LOG(INFO) << "KMEM DAX nodes are detected - will use it as a capacity pool";
pmem_memory_size = SIZE_MAX;
}
initAvailableDRAMSize();
}

MemoryResourceProvider::MemoryResourceProvider(const std::string& pmem_path, size_t size)
: dram_mem_resource_(new static_kind_memory_resource_type(libmemkind::kinds::REGULAR))
, mem_resources_(3, dram_mem_resource_.get()) {
initAvailableDRAMSize();
initPmm(pmem_path, size);
}

std::pmr::memory_resource* MemoryResourceProvider::get(const MemRequirements& req) const {
CHECK(req < mem_resources_.size());
CHECK(mem_resources_[req]);
return mem_resources_[req];
}

size_t MemoryResourceProvider::getAvailableMemorySize(
std::pmr::memory_resource* mem_resource) const {
if (dram_mem_resource_.get() == mem_resource) {
return dram_memory_size;
}

if (pmem_mem_resource_.get() == mem_resource) {
return pmem_memory_size;
}

throw std::runtime_error("Memory type unidentified");
}

MemType MemoryResourceProvider::getMemoryType(
std::pmr::memory_resource* memory_resource) const {
if (dram_mem_resource_.get() == memory_resource) {
return DRAM;
}
if (pmem_mem_resource_.get() == memory_resource) {
return PMEM;
}

throw std::runtime_error("Memory type unidentified");
}

std::vector<std::pmr::memory_resource*> MemoryResourceProvider::getOrderByBandwidth()
const {
CHECK(dram_mem_resource_);
std::vector<std::pmr::memory_resource*> res;
// TODO: Once we have HBM, we need to add it to the resulting vector first.

res.emplace_back(dram_mem_resource_.get());
if (pmem_mem_resource_)
res.emplace_back(pmem_mem_resource_.get());

return res;
}

void MemoryResourceProvider::initPmm(const std::string& pmem_path, size_t size) {
if (isDAXPath(pmem_path)) {
LOG(INFO) << pmem_path << " is on DAX-enabled file system.";
} else {
LOG(WARNING) << pmem_path << " is not on DAX-enabled file system.";
}

if (size == 0) {
initAvailablePMEMSize(pmem_path);
} else {
pmem_memory_size = size;
}

pmem_mem_resource_ =
std::make_unique<pmem_memory_resource_type>(pmem_path, pmem_memory_size);
mem_resources_[CAPACITY] = pmem_mem_resource_.get();
CHECK(mem_resources_[CAPACITY]);
}

bool MemoryResourceProvider::isDAXPath(const std::string& path) const {
int status = memkind_check_dax_path(path.c_str());
if (status) {
return false;
}

return true;
}

void MemoryResourceProvider::initAvailablePMEMSize(std::string path) {
std::error_code ec;
const std::filesystem::space_info si = std::filesystem::space(path, ec);
if (!ec) {
pmem_memory_size = static_cast<size_t>(si.capacity);
} else {
LOG(FATAL) << "Invalid pmem path: impossible to determine size of the pmem memory";
return;
}
}

void MemoryResourceProvider::initAvailableDRAMSize() {
// TODO: this implementation is incorrect for hetero memory
// Memkind will provide proper implementation soon.
// Will update this function once we have correct implementation from Memkind.
#ifdef __APPLE__
int mib[2];
size_t physical_memory;
size_t length;
// Get the Physical memory size
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
length = sizeof(size_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);
dram_memory_size = physical_memory;
#elif defined(_MSC_VER)
MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
dram_memory_size = status.ullTotalPhys;
#else // Linux
long pages = sysconf(_SC_PHYS_PAGES);
long page_size = sysconf(_SC_PAGE_SIZE);
dram_memory_size = pages * page_size;
#endif
}
} // namespace Buffer_Namespace
45 changes: 45 additions & 0 deletions DataMgr/Allocators/HeteroMem/MemResourceProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: BSD-2-Clause
/* Copyright (C) 2020 Intel Corporation. */

#pragma once

#include <memory_resource>
#include <string>
#include <vector>

namespace Buffer_Namespace {

enum MemRequirements { CAPACITY, HIGH_BDWTH, LOW_LATENCY };

enum MemType { DRAM, PMEM, HBM };

class MemoryResourceProvider {
public:
MemoryResourceProvider();

explicit MemoryResourceProvider(const std::string& pmem_path, size_t size);

std::pmr::memory_resource* get(const MemRequirements& req) const;
MemType getMemoryType(std::pmr::memory_resource* other) const;
size_t getAvailableMemorySize(std::pmr::memory_resource* mem_resource) const;
std::vector<std::pmr::memory_resource*> getOrderByBandwidth() const;

private:
void initPmm(const std::string& pmem_path, size_t size);

bool isDAXPath(const std::string& path) const;

void initAvailablePMEMSize(std::string path);
void initAvailableDRAMSize();

using mem_resources_storage_type = std::vector<std::pmr::memory_resource*>;

std::unique_ptr<std::pmr::memory_resource> dram_mem_resource_;
std::unique_ptr<std::pmr::memory_resource> pmem_mem_resource_;
size_t dram_memory_size;
size_t pmem_memory_size;

mem_resources_storage_type mem_resources_;
};

} // namespace Buffer_Namespace