diff --git a/CMakeLists.txt b/CMakeLists.txt index 5bb2570e..90abfd42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,8 +119,13 @@ set(SOURCES_CRYPTO ) if (WITH_HWLOC) + list(APPEND HEADERS_CRYPTO + src/crypto/common/NUMAMemoryPool.h + ) + list(APPEND SOURCES_CRYPTO - src/crypto/common/VirtualMemory_hwloc.cpp + src/crypto/common/NUMAMemoryPool.cpp + src/crypto/common/VirtualMemory_hwloc.cpp ) endif() diff --git a/src/crypto/common/NUMAMemoryPool.cpp b/src/crypto/common/NUMAMemoryPool.cpp new file mode 100644 index 00000000..8c48b4ca --- /dev/null +++ b/src/crypto/common/NUMAMemoryPool.cpp @@ -0,0 +1,106 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2018-2019 tevador + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#include "crypto/common/NUMAMemoryPool.h" +#include "crypto/common/VirtualMemory.h" +#include "backend/cpu/Cpu.h" +#include "crypto/common/MemoryPool.h" + + +#include + + +namespace xmrig { + + +constexpr size_t pageSize = 2 * 1024 * 1024; + + +} // namespace xmrig + + +xmrig::NUMAMemoryPool::NUMAMemoryPool(size_t size, bool hugePages) : + m_hugePages(hugePages), + m_nodeSize(std::max(size / Cpu::info()->nodes(), 1)), + m_size(size) +{ +} + + +xmrig::NUMAMemoryPool::~NUMAMemoryPool() +{ + for (auto kv : m_map) { + delete kv.second; + } +} + + +bool xmrig::NUMAMemoryPool::isHugePages(uint32_t node) const +{ + if (!m_size) { + return false; + } + + return getOrCreate(node)->isHugePages(node); +} + + +uint8_t *xmrig::NUMAMemoryPool::get(size_t size, uint32_t node) +{ + if (!m_size) { + return nullptr; + } + + return getOrCreate(node)->get(size, node); +} + + +void xmrig::NUMAMemoryPool::release(uint32_t node) +{ + const auto pool = get(node); + if (pool) { + pool->release(node); + } +} + + +xmrig::IMemoryPool *xmrig::NUMAMemoryPool::get(uint32_t node) const +{ + return m_map.count(node) ? m_map.at(node) : nullptr; +} + + +xmrig::IMemoryPool *xmrig::NUMAMemoryPool::getOrCreate(uint32_t node) const +{ + auto pool = get(node); + if (!pool) { + pool = new MemoryPool(m_nodeSize, m_hugePages, node); + m_map.insert({ node, pool }); + } + + return pool; +} diff --git a/src/crypto/common/NUMAMemoryPool.h b/src/crypto/common/NUMAMemoryPool.h new file mode 100644 index 00000000..4e030494 --- /dev/null +++ b/src/crypto/common/NUMAMemoryPool.h @@ -0,0 +1,72 @@ +/* XMRig + * Copyright 2010 Jeff Garzik + * Copyright 2012-2014 pooler + * Copyright 2014 Lucas Jones + * Copyright 2014-2016 Wolf9466 + * Copyright 2016 Jay D Dee + * Copyright 2017-2018 XMR-Stak , + * Copyright 2018 Lee Clagett + * Copyright 2018-2019 SChernykh + * Copyright 2018-2019 tevador + * Copyright 2016-2019 XMRig , + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef XMRIG_NUMAMEMORYPOOL_H +#define XMRIG_NUMAMEMORYPOOL_H + + +#include "backend/common/interfaces/IMemoryPool.h" +#include "base/tools/Object.h" + + +#include + + +namespace xmrig { + + +class IMemoryPool; + + +class NUMAMemoryPool : public IMemoryPool +{ +public: + XMRIG_DISABLE_COPY_MOVE_DEFAULT(NUMAMemoryPool) + + NUMAMemoryPool(size_t size, bool hugePages); + ~NUMAMemoryPool() override; + +protected: + bool isHugePages(uint32_t node) const override; + uint8_t *get(size_t size, uint32_t node) override; + void release(uint32_t node) override; + +private: + IMemoryPool *get(uint32_t node) const; + IMemoryPool *getOrCreate(uint32_t node) const; + + bool m_hugePages = true; + size_t m_nodeSize = 0; + size_t m_size = 0; + mutable std::map m_map; +}; + + +} /* namespace xmrig */ + + + +#endif /* XMRIG_NUMAMEMORYPOOL_H */ diff --git a/src/crypto/common/VirtualMemory.cpp b/src/crypto/common/VirtualMemory.cpp index 332c07fd..95030846 100644 --- a/src/crypto/common/VirtualMemory.cpp +++ b/src/crypto/common/VirtualMemory.cpp @@ -32,6 +32,11 @@ #include "crypto/common/portable/mm_malloc.h" +#ifdef XMRIG_FEATURE_HWLOC +# include "crypto/common/NUMAMemoryPool.h" +#endif + + #include #include @@ -111,5 +116,12 @@ void xmrig::VirtualMemory::init(bool hugePages, int poolSize) osInit(); } - pool = new MemoryPool(poolSize < 0 ? Cpu::info()->threads() : poolSize, hugePages); +# ifdef XMRIG_FEATURE_HWLOC + if (Cpu::info()->nodes() > 1) { + pool = new NUMAMemoryPool(align(poolSize < 0 ? Cpu::info()->threads() : poolSize, Cpu::info()->nodes()), hugePages); + } else +# endif + { + pool = new MemoryPool(poolSize < 0 ? Cpu::info()->threads() : poolSize, hugePages); + } } diff --git a/src/crypto/rx/RxVm.cpp b/src/crypto/rx/RxVm.cpp index 526b5ce6..e8d615e8 100644 --- a/src/crypto/rx/RxVm.cpp +++ b/src/crypto/rx/RxVm.cpp @@ -43,11 +43,9 @@ xmrig::RxVm::RxVm(RxDataset *dataset, uint8_t *scratchpad, bool softAes) if (!dataset->cache() || dataset->cache()->isJIT()) { m_flags |= RANDOMX_FLAG_JIT; - m_vm = randomx_create_vm(static_cast(m_flags), nullptr, dataset->get(), scratchpad); - } - else { - m_vm = randomx_create_vm(static_cast(m_flags), dataset->cache()->get(), dataset->get(), scratchpad); } + + m_vm = randomx_create_vm(static_cast(m_flags), dataset->cache() ? dataset->cache()->get() : nullptr, dataset->get(), scratchpad); }