Skip to content

Commit

Permalink
Merge pull request #243 from LLNL/release/v0.22
Browse files Browse the repository at this point in the history
Release/v0.22
  • Loading branch information
KIwabuchi committed Oct 12, 2022
2 parents c47a83e + 854bd33 commit 9e195e7
Show file tree
Hide file tree
Showing 24 changed files with 560 additions and 243 deletions.
16 changes: 8 additions & 8 deletions CMakeLists.txt
Expand Up @@ -5,13 +5,19 @@ include(FetchContent)
# -------------------------------------------------------------------------------- #
# CMake policy
# -------------------------------------------------------------------------------- #
cmake_policy(SET CMP0077 NEW)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13")
cmake_policy(SET CMP0077 NEW)
endif()

if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24")
cmake_policy(SET CMP0135 NEW)
endif()

# -------------------------------------------------------------------------------- #
# Metall general configuration
# -------------------------------------------------------------------------------- #
project(Metall
VERSION 0.21
VERSION 0.22
DESCRIPTION "A persistent memory allocator for data-centric analytics"
HOMEPAGE_URL "https://github.com/LLNL/metall")

Expand Down Expand Up @@ -85,7 +91,6 @@ option(BUILD_TEST "Build the test" OFF)
option(RUN_LARGE_SCALE_TEST "Run large scale tests" OFF)
option(RUN_BUILD_AND_TEST_WITH_CI "Perform build and basic test with CI" OFF)
option(BUILD_VERIFICATION "Build verification directory" OFF)
option(LOGGING "Logging" OFF)
option(USE_SORTED_BIN "Use VM space aware algorithm in the bin directory" OFF)

set(DEFAULT_VM_RESERVE_SIZE "0" CACHE STRING
Expand Down Expand Up @@ -192,11 +197,6 @@ if (INITIAL_SEGMENT_SIZE GREATER 0)
message(STATUS "METALL_INITIAL_SEGMENT_SIZE=${INITIAL_SEGMENT_SIZE}")
endif ()

if (LOGGING)
list(APPEND METALL_DEFS "METALL_ENABLE_LOGGING")
message(STATUS "Enable logging")
endif ()

if (USE_SORTED_BIN)
list(APPEND METALL_DEFS "METALL_USE_SORTED_BIN")
message(STATUS "Use VM space aware algorithm in the bin directory")
Expand Down
3 changes: 2 additions & 1 deletion bench/CMakeLists.txt
@@ -1,4 +1,5 @@
add_subdirectory(simple_alloc)
add_subdirectory(adjacency_list)
add_subdirectory(bfs)
add_subdirectory(rand_engine)
add_subdirectory(rand_engine)
add_subdirectory(mapping)
2 changes: 1 addition & 1 deletion bench/adjacency_list/bench_driver.hpp
Expand Up @@ -297,7 +297,7 @@ inline void dump_adj_list(const adjacency_list_type &adj_list, const std::string
for (auto key_itr = adj_list.keys_begin(), key_end = adj_list.keys_end(); key_itr != key_end; ++key_itr) {
for (auto value_itr = adj_list.values_begin(key_itr->first), value_end = adj_list.values_end(key_itr->first);
value_itr != value_end; ++value_itr) {
ofs << key_itr->first << "\t" << *value_itr << "\n";
ofs << key_itr->first << " " << *value_itr << "\n";
}
}
ofs.close();
Expand Down
8 changes: 4 additions & 4 deletions bench/adjacency_list/test/test.sh
Expand Up @@ -18,14 +18,14 @@ compare() {
num_elements=$(< ${file1} wc -l)
if [[ ${num_elements} -eq 0 ]]; then
echo "<< ${file1} is empty!! >>"
exit
exit 1
fi

echo "Sort the dumped edges"
sort -k 1,1n -k2,2n < ${file1} > ${DATASTORE_DIR_ROOT}/file1_sorted
check_program_exit_status

sort -k 1,1n -k2,2n < ${file1} > ${DATASTORE_DIR_ROOT}/file2_sorted
sort -k 1,1n -k2,2n < ${file2} > ${DATASTORE_DIR_ROOT}/file2_sorted
check_program_exit_status

echo "Compare the dumped edges"
Expand Down Expand Up @@ -74,9 +74,10 @@ main() {
echo "Create Test"
./run_adj_list_bench_metall -o ${DATASTORE_DIR_ROOT}/metall_test_dir -d ${DATASTORE_DIR_ROOT}/adj_out ${DATA}*
check_program_exit_status
rm -f ${DATASTORE_DIR_ROOT}/adj_ref
cat ${DATA}* >> ${DATASTORE_DIR_ROOT}/adj_ref
compare "${DATASTORE_DIR_ROOT}/adj_out" "${DATASTORE_DIR_ROOT}/adj_ref"
/bin/rm -f "${DATASTORE_DIR_ROOT}/adj_out" "${DATASTORE_DIR_ROOT}/adj_ref"
/bin/rm -f "${DATASTORE_DIR_ROOT}/adj_out"

# Open the adj-list with the open mode and add more edges
echo ""
Expand All @@ -91,7 +92,6 @@ main() {
echo "Open Test"
./test/open_metall -o ${DATASTORE_DIR_ROOT}/metall_test_dir -d ${DATASTORE_DIR_ROOT}/adj_out_open
check_program_exit_status
cat ${DATA}* >> ${DATASTORE_DIR_ROOT}/adj_ref
compare "${DATASTORE_DIR_ROOT}/adj_out_open" "${DATASTORE_DIR_ROOT}/adj_ref"

# Open the adj-list and destroy it to test memory leak
Expand Down
1 change: 1 addition & 0 deletions bench/mapping/CMakeLists.txt
@@ -0,0 +1 @@
add_metall_executable(run_mapping_bench run_mapping_bench.cpp)
206 changes: 206 additions & 0 deletions bench/mapping/run_mapping_bench.cpp
@@ -0,0 +1,206 @@
#include <iostream>
#include <random>
#include <string>
#include <map>
#include <vector>
#include <metall/metall.hpp>
#include <metall/utility/random.hpp>
#include <metall/detail/time.hpp>
#include <metall/detail/mmap.hpp>

using rand_engine = metall::utility::rand_512;
static constexpr std::size_t k_page_size = 4096;

namespace {
namespace mdtl = metall::mtlldetail;
}

auto random_write_by_page(const std::size_t size, unsigned char *const map) {
const auto num_pages = size / k_page_size;
rand_engine rand_engine(123);
std::uniform_int_distribution<> dist(0, num_pages - 1);

const auto s = mdtl::elapsed_time_sec();
for (std::size_t i = 0; i < num_pages; ++i) {
const auto page_no = dist(rand_engine);
const off_t offset = static_cast<off_t>(page_no * k_page_size);
map[offset] = '0';
}
const auto t = mdtl::elapsed_time_sec(s);

return t;
}

auto random_read_by_page(const std::size_t size, const unsigned char *const map) {
const auto num_pages = size / k_page_size;
rand_engine rand_engine(1234);
std::uniform_int_distribution<> dist(0, num_pages - 1);

const auto s = mdtl::elapsed_time_sec();
for (std::size_t i = 0; i < num_pages; ++i) {
const auto page_no = dist(rand_engine);
const off_t offset = static_cast<off_t>(page_no * k_page_size);
[[maybe_unused]] volatile char dummy = map[offset];
}
const auto t = mdtl::elapsed_time_sec(s);

return t;
}

int create_normal_file(std::string_view path) {
const int fd = ::open(path.data(), O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
if (fd == -1) {
std::cerr << "Failed to create a file" << std::endl;
std::abort();
}
return fd;
}

int create_tmpfile(std::string_view path) {
static char file_template[] = "/mmap.XXXXXX";

char fullname[path.size() + sizeof(file_template)];
(void)strcpy(fullname, path.data());
(void)strcat(fullname, file_template);

int fd = -1;
if ((fd = mkstemp(fullname)) < 0) {
std::perror("Could not create temporary file");
std::abort();
}

(void)unlink(fullname);

return fd;
}

void extend_file(const int fd, const std::size_t size, const bool fill_with_zero) {
if (!mdtl::extend_file_size(fd, size, fill_with_zero)) {
std::cerr << "Failed to extend file" << std::endl;
std::abort();
}
}

auto map_file(const int fd, const std::size_t size) {
static constexpr int k_map_nosync =
#ifdef MAP_NOSYNC
MAP_NOSYNC;
#else
0;
#warning "MAP_NOSYNC is not defined"
#endif

auto *const map = mdtl::os_mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | k_map_nosync, fd, 0);
if (!map) {
std::cerr << " Failed mapping" << std::endl;
std::abort();
}

return map;
}

void close_file(const int fd) {
if (!mdtl::os_close(fd)) {
std::cerr << __LINE__ << " Failed to close file" << std::endl;
std::abort();
}
}

void unmap(void *const addr, const std::size_t size) {
if (!mdtl::munmap(addr, size, false)) {
std::cerr << __LINE__ << " Failed to munmap" << std::endl;
std::abort();
}
}

/// \brief Run benchmark to evaluate different mapping methods
void run_bench_one_time(std::string_view dir_path,
const std::size_t length,
const bool init_file_writing_zero,
std::map<std::string, std::vector<double>> &time_table) {

const auto bench_core = [&time_table, length](std::string_view mode, unsigned char *const map) {
time_table[std::string(mode) + " write"].push_back(random_write_by_page(length, map));
time_table[std::string(mode) + " read"].push_back(random_read_by_page(length, map));
};

// Use 'new'
{
auto *const map = new unsigned char[length];
bench_core("malloc", map);
delete[] map;
}

// Use a normal file and mmap
{
std::string file_path{std::string(dir_path) + "/map-file"};
const int fd = create_normal_file(file_path);
extend_file(fd, length, init_file_writing_zero);
auto *const map = static_cast<unsigned char *>(map_file(fd, length));
close_file(fd);
bench_core("Normal-file", map);
unmap(map, length);
}

// Use tmpfile and mmap
{
const int fd = create_tmpfile(dir_path);
extend_file(fd, length, init_file_writing_zero);
auto *const map = static_cast<unsigned char *>(map_file(fd, length));
close_file(fd);
bench_core("tmpfile", map);
unmap(map, length);
}

// Use Metall
{
metall::manager manager(metall::create_only, dir_path.data());
auto *map = static_cast<unsigned char *>(manager.allocate(length));
bench_core("Metall", map);
manager.deallocate(map);
}
metall::manager::remove(dir_path.data());

}

void run_bench(std::string_view dir_path,
const std::size_t num_repeats,
const std::size_t length,
const bool init_file_writing_zero) {
std::cout << "\n----------" << std::endl;
std::cout << "Directory Path:\t" << dir_path
<< "\nRepeats:\t" << num_repeats
<< "\nLength:\t" << length
<< "\nInit w/ writing:\t" << init_file_writing_zero
<< "\n" << std::endl;

// Run bench
std::map<std::string, std::vector<double>> time_table;
for (std::size_t i = 0; i < num_repeats; ++i) {
run_bench_one_time(dir_path, length, init_file_writing_zero, time_table);
}

// Show results
for (const auto &entry: time_table) {
const auto &mode = entry.first;
const auto &times = entry.second;
std::cout << std::fixed;
std::cout << std::setprecision(2);
std::cout << mode << " took (s)\t"
<< std::accumulate(times.begin(), times.end(), 0.0f) / times.size() << std::endl;
}
}

int main() {
static constexpr std::size_t size = k_page_size * 1024 * 10;
const int num_repeats = 10;

#if defined(__linux__)
run_bench("/dev/shm", num_repeats, size, false);
run_bench("/dev/shm", num_repeats, size, true);
#endif
run_bench("/tmp", num_repeats, size, false);
run_bench("/tmp", num_repeats, size, true);

return 0;
}
2 changes: 1 addition & 1 deletion docs/Doxyfile.in
Expand Up @@ -38,7 +38,7 @@ PROJECT_NAME = "Metall"
# could be handy for archiving the generated documentation or if some version
# control system is used.

PROJECT_NUMBER = v0.21
PROJECT_NUMBER = v0.22

# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
Expand Down
31 changes: 20 additions & 11 deletions docs/readthedocs/about/publication.md
@@ -1,17 +1,26 @@
# Publication

## Metall: A Persistent Memory Allocator Enabling Graph Processing
## Metall: A persistent memory allocator for data-centric analytics

```
Keita Iwabuchi, Karim Youssef, Kaushik Velusamy, Maya Gokhale, Roger Pearce,
Metall: A persistent memory allocator for data-centric analytics,
Parallel Computing, 2022, 102905, ISSN 0167-8191, https://doi.org/10.1016/j.parco.2022.102905.
```

- [Parallel Computing](https://www.sciencedirect.com/science/article/abs/pii/S0167819122000114) (journal)

[Available PDF](https://www.osti.gov/servlets/purl/1576900)
- [arXiv](https://arxiv.org/abs/2108.07223) (preprint)

## Metall: A Persistent Memory Allocator Enabling Graph Processing

A page in IEEE Xplore is [here](https://ieeexplore.ieee.org/document/8945094)
```text
@INPROCEEDINGS{8945094,
author={K. {Iwabuchi} and L. {Lebanoff} and M. {Gokhale} and R. {Pearce}},
booktitle={2019 IEEE/ACM 9th Workshop on Irregular Applications: Architectures and Algorithms (IA3)},
title={Metall: A Persistent Memory Allocator Enabling Graph Processing},
year={2019},
pages={39-44},
doi={10.1109/IA349570.2019.00012},
month={Nov},}
K. Iwabuchi, L. Lebanoff, M. Gokhale and R. Pearce,
"Metall: A Persistent Memory Allocator Enabling Graph Processing,"
2019 IEEE/ACM 9th Workshop on Irregular Applications: Architectures and Algorithms (IA3), 2019,
pp. 39-44, doi: 10.1109/IA349570.2019.00012.
```

- [Available PDF](https://www.osti.gov/servlets/purl/1576900)

- A page in IEEE Xplore is [here](https://ieeexplore.ieee.org/document/8945094)
6 changes: 3 additions & 3 deletions docs/readthedocs/basics/compile_time_options.md
@@ -1,6 +1,6 @@
# Compile-time Options

There are some compile-time options (macro) as follows to configure the behavior of Metall:
There are some compile-time options (C/C++ macro) as follows to configure the behavior of Metall:


- METALL_DISABLE_FREE_FILE_SPACE
Expand All @@ -10,13 +10,13 @@ There are some compile-time options (macro) as follows to configure the behavior
- METALL_DEFAULT_VM_RESERVE_SIZE=*bytes*
- The default virtual memory reserve size
- An internally defined value is used if 0 is specified
- Wll be rounded up to a multiple of the page size internally
- Wll be rounded up to a multiple of the system page size (e.g., 4 KB) internally


- METALL_INITIAL_SEGMENT_SIZE=*bytes*
- The initial segment size
- Use the internally defined value if 0 is specified
- Wll be rounded up to a multiple of the page size internally
- Wll be rounded up to a multiple of the system page size internally


- METALL_FREE_SMALL_OBJECT_SIZE_HINT=*bytes*
Expand Down

0 comments on commit 9e195e7

Please sign in to comment.