SEAL开源库源码04
文章目录
seal/memorymanager.h
引用的头文件
#include "seal/util/defines.h"
#include "seal/util/globals.h"
#include "seal/util/mempool.h"
#include <memory>
#include <stdexcept>
#include <unordered_map>
#include <utility>
/*
For .NET Framework wrapper support (C++/CLI) we need to
(1) compile the MemoryManager class as thread-unsafe because C++
mutexes cannot be brought through C++/CLI layer;
(2) disable thread-safe memory pools.
*/
#ifndef _M_CEE
#include <mutex>
#include <thread>
#endif
回想一下,globals.h 定义了一些默认安全参数选择。
class MemoryPoolHandle 类
类说明
/**
Manages a shared pointer to a memory pool. Microsoft SEAL uses memory pools
for improved performance due to the large number of memory allocations
needed by the homomorphic encryption operations, and the underlying polynomial
arithmetic. The library automatically creates a shared global memory pool
that is used for all dynamic allocations by default, and the user can
optionally create any number of custom memory pools to be used instead.
@par Uses in Multi-Threaded Applications
Sometimes the user might want to use specific memory pools for dynamic
allocations in certain functions. For example, in heavily multi-threaded
applications allocating concurrently from a shared memory pool might lead
to significant performance issues due to thread contention. For these cases
Microsoft SEAL provides overloads of the functions that take a MemoryPoolHandle
as an additional argument, and uses the associated memory pool for all dynamic
allocations inside the function. Whenever these functions are called, the
user can then simply pass a thread-local MemoryPoolHandle to be used.
@par Thread-Unsafe Memory Pools
While memory pools are by default thread-safe, in some cases it suffices
to have a memory pool be thread-unsafe. To get a little extra performance,
the user can optionally create such thread-unsafe memory pools and use them
just as they would use thread-safe memory pools.
@par Initialized and Uninitialized Handles
A MemoryPoolHandle has to be set to point either to the global memory pool,
or to a new memory pool. If this is not done, the MemoryPoolHandle is
said to be uninitialized, and cannot be used. Initialization simply means
assigning MemoryPoolHandle::Global() or MemoryPoolHandle::New() to it.
@par Managing Lifetime
Internally, the MemoryPoolHandle wraps an std::shared_ptr pointing to
a memory pool class. Thus, as long as a MemoryPoolHandle pointing to
a particular memory pool exists, the pool stays alive. Classes such as
Evaluator and Ciphertext store their own local copies of a MemoryPoolHandle
to guarantee that the pool stays alive as long as the managing object
itself stays alive. The global memory pool is implemented as a global
std::shared_ptr to a memory pool class, and is thus expected to stay
alive for the entire duration of the program execution. Note that it can
be problematic to create other global objects that use the memory pool
e.g. in their constructor, as one would have to ensure the initialization
order of these global variables to be correct (i.e. global memory pool
first).
*/
下面为翻译
管理指向内存池的共享指针。由于同态加密操作和底层多项式算法需要大量内存分配,Microsoft SEAL使用内存池来提高性能。该库自动创建一个共享全局内存池,默认情况下用于所有动态分配,用户可以选择创建任意数量的自定义内存池。
有时,用户可能希望在某些函数中使用特定的内存池进行动态分配。例如,在高度多线程的应用程序中,从共享内存池中并发分配内存可能会由于线程争用而导致严重的性能问题。对于这些情况,Microsoft SEAL提供了函数的重载,这些函数以MemoryPoolHandle作为附加参数,并为函数内的所有动态分配使用关联的内存池。每当调用这些函数时,用户就可以简单地传递一个线程本地MemoryPoolHandle来使用。
虽然内存池在默认情况下是线程安全的,但在某些情况下,让内存池是线程不安全的就足够了。为了获得一点额外的性能,用户可以有选择地创建这样的线程不安全的内存池,并像使用线程安全的内存池一样使用它们。
必须将MemoryPoolHandle设置为指向全局内存池,或者指向一个新的内存池。如果不这样做,则称MemoryPoolHandle是未初始化的,不能使用。初始化仅仅意味着给它分配MemoryPoolHandle::Global()或MemoryPoolHandle::New()。
在内部,MemoryPoolHandle封装了指向内存池类的std::shared_ptr。因此,只要指向特定内存池的MemoryPoolHandle存在,该池就保持活动。Evaluator和Ciphertext等类存储MemoryPoolHandle的自己的本地副本,以确保只要管理对象本身保持活动,池就保持活动。全局内存池是作为内存池类的全局std::shared_ptr实现的,因此期望在程序执行的整个过程中都保持活动状态。注意,创建其他使用内存池的全局对象可能会有问题,例如在它们的构造函数中,因为必须确保这些全局变量的初始化顺序是正确的(即全局内存池优先)。
私有成员:一个指向 MemoryPool 的 shared_ptr
private:
std::shared_ptr<util::MemoryPool> pool_ = nullptr;
构造函数们
/**
Creates a new uninitialized MemoryPoolHandle.
*/
MemoryPoolHandle() = default;
/**
Creates a MemoryPoolHandle pointing to a given MemoryPool object.
*/
MemoryPoolHandle(std::shared_ptr<util::MemoryPool> pool) noexcept : pool_(std::move(pool))
{
}
/**
Creates a copy of a given MemoryPoolHandle. As a result, the created
MemoryPoolHandle will point to the same underlying memory pool as the
copied instance.
@param[in] copy The MemoryPoolHandle to copy from
*/
MemoryPoolHandle(const MemoryPoolHandle ©) noexcept
{
operator=(copy);
}
/**
Creates a new MemoryPoolHandle by moving a given one. As a result, the
moved MemoryPoolHandle will become uninitialized.
@param[in] source The MemoryPoolHandle to move from
*/
MemoryPoolHandle(MemoryPoolHandle &&source) noexcept
{
operator=(std::move(source));
}
赋值运算符重载
/**
Overwrites the MemoryPoolHandle instance with the specified instance. As
a result, the current MemoryPoolHandle will point to the same underlying
memory pool as the assigned instance.
@param[in] assign The MemoryPoolHandle instance to assign to the current
instance
*/
inline MemoryPoolHandle &operator=(const MemoryPoolHandle &assign) noexcept
{
pool_ = assign.pool_;
return *this;
}
/**
Moves a specified MemoryPoolHandle instance to the current instance. As
a result, the assigned MemoryPoolHandle will become uninitialized.
@param[in] assign The MemoryPoolHandle instance to assign to the current
instance
*/
inline MemoryPoolHandle &operator=(MemoryPoolHandle &&assign) noexcept
{
pool_ = std::move(assign.pool_);
return *this;
}
static Global 和 static ThreadLocal 函数,返回全局 MemoryPoolHandle 对象
/**
Returns a MemoryPoolHandle pointing to the global memory pool.
*/
SEAL_NODISCARD inline static MemoryPoolHandle Global() noexcept
{
return util::global_variables::global_memory_pool; // 在 globals.h 中定义
}
#ifndef _M_CEE
/**
Returns a MemoryPoolHandle pointing to the thread-local memory pool.
*/
SEAL_NODISCARD inline static MemoryPoolHandle ThreadLocal() noexcept
{
return util::global_variables::tls_memory_pool;
}
#endif
static New 函数
/**
Returns a MemoryPoolHandle pointing to a new thread-safe memory pool.
@param[in] clear_on_destruction Indicates whether the memory pool data
should be cleared when destroyed. This can be important when memory pools
are used to store private data.
*/
SEAL_NODISCARD inline static MemoryPoolHandle New(bool clear_on_destruction = false)
{
return MemoryPoolHandle(std::make_shared<util::MemoryPoolMT>(clear_on_destruction));
}
返回一个引用
/**
Returns a reference to the internal memory pool that the MemoryPoolHandle
points to. This function is mainly for internal use.
@throws std::logic_error if the MemoryPoolHandle is uninitialized
*/
SEAL_NODISCARD inline operator util::MemoryPool &() const
{
if (!pool_)
{
throw std::logic_error("pool not initialized");
}
return *pool_.get();
}
pool_count 函数 Returns the number of different allocation sizes.
/**
Returns the number of different allocation sizes. This function returns
the number of different allocation sizes the memory pool pointed to by
the current MemoryPoolHandle has made. For example, if the memory pool has
only allocated two allocations of sizes 128 KB, this function returns 1.
If it has instead allocated one allocation of si