Skip to content

Commit

Permalink
Implemented Memory Provider for Heterogeneous memory.
Browse files Browse the repository at this point in the history
The idea is to add abstraction layer for heterogeneous memory.
The interface is built on top of C++ 17 std::pmr::memory_resource
interface.
  • Loading branch information
vinser52 committed Aug 23, 2021
1 parent 2f97526 commit 0902a18
Show file tree
Hide file tree
Showing 8 changed files with 452 additions and 9 deletions.
11 changes: 8 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,10 @@ else()
endif()
endif()

set(MEMKIND_REQUIRED_VERSION 1.11.0)
find_package(PkgConfig QUIET)
pkg_check_modules(memkind REQUIRED memkind>=${MEMKIND_REQUIRED_VERSION})

set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)

if(MSVC)
Expand Down Expand Up @@ -704,6 +708,7 @@ add_subdirectory(SQLFrontend)
add_subdirectory(TableArchiver)
add_subdirectory(ThriftHandler)
add_subdirectory(Geospatial)
add_subdirectory(HeteroMem)
add_subdirectory(Distributed)
add_subdirectory(UdfCompiler)

Expand All @@ -716,7 +721,7 @@ if(ENABLE_ODBC)
add_subdirectory(ODBC)
endif()

set(MAPD_LIBRARIES OSDependent Shared Catalog SqliteConnector MigrationMgr TableArchiver Parser Analyzer ImportExport QueryRunner QueryEngine QueryState LockMgr DataMgr Fragmenter Logger Geospatial)
set(MAPD_LIBRARIES OSDependent Shared Catalog SqliteConnector MigrationMgr TableArchiver Parser Analyzer ImportExport QueryRunner QueryEngine QueryState LockMgr DataMgr Fragmenter Logger Geospatial HeteroMem)

if("${MAPD_EDITION_LOWER}" STREQUAL "ee")
list(APPEND MAPD_LIBRARIES Distributed)
Expand Down Expand Up @@ -830,11 +835,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
6 changes: 6 additions & 0 deletions HeteroMem/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set(heteromem_source_files
MemResourceProvider.cpp)

add_library(HeteroMem ${heteromem_source_files})

target_link_libraries(HeteroMem ${memkind_LIBRARIES})
153 changes: 153 additions & 0 deletions HeteroMem/MemResourceProvider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// SPDX-License-Identifier: BSD-2-Clause
/* Copyright (C) 2020 Intel Corporation. */

#include "HeteroMem/MemResourceProvider.h"

#include "Logger/Logger.h"

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

#include <memory>

#include "memkind.h"
#include <filesystem>
#include <cstdint>
#include <unistd.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
53 changes: 53 additions & 0 deletions HeteroMem/MemResourceProvider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// SPDX-License-Identifier: BSD-2-Clause
/* Copyright (C) 2020 Intel Corporation. */

#pragma once

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


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
Loading

0 comments on commit 0902a18

Please sign in to comment.