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

fboemer/hexl-1.1.0 #332

Merged
merged 10 commits into from
May 11, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ if(SEAL_USE_INTEL_HEXL)
message(STATUS "Intel HEXL: download ...")
seal_fetch_thirdparty_content(ExternalIntelHEXL)
else()
find_package(HEXL 1.0.1)
find_package(HEXL 1.1.0)
if (NOT TARGET HEXL::hexl)
FATAL_ERROR("Intel HEXL: not found")
endif()
Expand Down Expand Up @@ -461,8 +461,12 @@ else()
endif()

if(SEAL_USE_INTEL_HEXL)
target_include_directories(seal_shared PRIVATE $<BUILD_INTERFACE:${hexl_SOURCE_DIR}/hexl/include>)
target_link_libraries(seal_shared PRIVATE hexl)
get_target_property(
HEXL_INCLUDE_DIR
HEXL::hexl
INTERFACE_INCLUDE_DIRECTORIES)
target_include_directories(seal_shared PUBLIC ${HEXL_INCLUDE_DIR})
target_link_libraries(seal_shared PRIVATE HEXL::hexl)
endif()
endif()

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ The optional dependencies and their tested versions (other versions may work as

| Optional dependency | Tested version | Use |
| ------------------------------------------------------ | -------------- | ------------------------------------------------ |
| [Intel HEXL](https://github.com/intel/hexl) | 1.0.1 | Acceleration of low-level kernels |
| [Intel HEXL](https://github.com/intel/hexl) | 1.1.0 | Acceleration of low-level kernels |
| [Microsoft GSL](https://github.com/microsoft/GSL) | 3.1.0 | API extensions |
| [ZLIB](https://github.com/madler/zlib) | 1.2.11 | Compressed serialization |
| [Zstandard](https://github.com/facebook/zstd) | 1.4.5 | Compressed serialization (much faster than ZLIB) |
Expand Down
4 changes: 2 additions & 2 deletions cmake/ExternalIntelHEXL.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
FetchContent_Declare(
hexl
PREFIX hexl
GIT_REPOSITORY https://github.com/intel/hexl.git
GIT_TAG v1.0.1
GIT_REPOSITORY https://github.com/intel/hexl
GIT_TAG 1.1.0
WeiDaiWD marked this conversation as resolved.
Show resolved Hide resolved
)
FetchContent_GetProperties(hexl)

Expand Down
111 changes: 110 additions & 1 deletion native/src/seal/util/intel_seal_ext.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,119 @@
#pragma once

#ifdef SEAL_USE_INTEL_HEXL
#include "seal/memorymanager.h"
#include "seal/util/locks.h"
#include <unordered_map>
#include "hexl/hexl.hpp"

namespace intel
{
namespace hexl
{
// Single threaded SEAL allocator adapter
template <>
struct NTT::AllocatorAdapter<seal::MemoryPoolHandle>
: public AllocatorInterface<NTT::AllocatorAdapter<seal::MemoryPoolHandle>>
{
AllocatorAdapter(seal::MemoryPoolHandle &&handle) : handle_(std::move(handle))
WeiDaiWD marked this conversation as resolved.
Show resolved Hide resolved
{}

~AllocatorAdapter()
{}

// interface implementations
void *allocate_impl(std::size_t bytes_count)
{
cache_.push_back(static_cast<seal::util::MemoryPool &>(handle_).get_for_byte_count(bytes_count));
return cache_.back().get();
}

void deallocate_impl(void *p, std::size_t n)
{
(void)n;
auto it = std::remove_if(
cache_.begin(), cache_.end(),
[p](const seal::util::Pointer<seal::seal_byte> &seal_pointer) { return p == seal_pointer.get(); });

#ifdef SEAL_DEBUG
if (it == cache_.end())
{
throw std::logic_error("Inconsistent single-threaded allocator cache");
}
#endif
cache_.erase(it, cache_.end());
}

private:
seal::MemoryPoolHandle handle_;
std::vector<seal::util::Pointer<seal::seal_byte>> cache_;
};

// Thread safe policy
struct SimpleThreadSafePolicy
{
SimpleThreadSafePolicy() : m_ptr(std::make_unique<std::mutex>())
{}

std::unique_lock<std::mutex> locker()
{
return std::unique_lock<std::mutex>{ *m_ptr };
};

private:
std::unique_ptr<std::mutex> m_ptr;
WeiDaiWD marked this conversation as resolved.
Show resolved Hide resolved
};

// Multithreaded SEAL allocator adapter
template <>
struct NTT::AllocatorAdapter<seal::MemoryPoolHandle, SimpleThreadSafePolicy>
: public AllocatorInterface<NTT::AllocatorAdapter<seal::MemoryPoolHandle, SimpleThreadSafePolicy>>
{
AllocatorAdapter(seal::MemoryPoolHandle &&handle, SimpleThreadSafePolicy &&policy)
WeiDaiWD marked this conversation as resolved.
Show resolved Hide resolved
: handle_(std::move(handle)), policy_(std::move(policy))
{}

~AllocatorAdapter()
{}
// interface implementations
void *allocate_impl(std::size_t bytes_count)
{
{
// to prevent inline optimization with deadlock
auto accessor = policy_.locker();
cache_.push_back(static_cast<seal::util::MemoryPool &>(handle_).get_for_byte_count(bytes_count));
return cache_.back().get();
}
}

void deallocate_impl(void *p, std::size_t n)
{
(void)n;
{
// to prevent inline optimization with deadlock
auto accessor = policy_.locker();
auto it = std::remove_if(
cache_.begin(), cache_.end(), [p](const seal::util::Pointer<seal::seal_byte> &seal_pointer) {
return p == seal_pointer.get();
});

#ifdef SEAL_DEBUG
if (it == cache_.end())
{
throw std::logic_error("Inconsistent multi-threaded allocator cache");
}
#endif
cache_.erase(it, cache_.end());
}
}

private:
seal::MemoryPoolHandle handle_;
SimpleThreadSafePolicy policy_;
std::vector<seal::util::Pointer<seal::seal_byte>> cache_;
};
} // namespace hexl

namespace seal_ext
{
struct HashPair
Expand Down Expand Up @@ -61,7 +168,9 @@ namespace intel
auto ntt_it = ntt_cache_.find(key);
if (ntt_it == ntt_cache_.end())
{
ntt_it = ntt_cache_.emplace(std::move(key), intel::hexl::NTT(N, modulus, root)).first;
intel::hexl::NTT ntt(
N, modulus, root, seal::MemoryManager::GetPool(), intel::hexl::SimpleThreadSafePolicy{});
ntt_it = ntt_cache_.emplace(std::move(key), std::move(ntt)).first;
}
return ntt_it->second;
}
Expand Down
8 changes: 8 additions & 0 deletions native/src/seal/util/polyarithsmallmod.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ namespace seal
}
#endif

#ifdef SEAL_USE_INTEL_HEXL
intel::hexl::EltwiseAddMod(result, poly, scalar, coeff_count, modulus.value());
#else
SEAL_ITERATE(iter(poly, result), coeff_count, [&](auto I) {
const uint64_t x = get<0>(I);
get<1>(I) = add_uint_mod(x, scalar, modulus);
});
#endif
}

void sub_poly_scalar_coeffmod(
Expand All @@ -65,10 +69,14 @@ namespace seal
}
#endif

#ifdef SEAL_USE_INTEL_HEXL
intel::hexl::EltwiseSubMod(result, poly, scalar, coeff_count, modulus.value());
#else
SEAL_ITERATE(iter(poly, result), coeff_count, [&](auto I) {
const uint64_t x = get<0>(I);
get<1>(I) = sub_uint_mod(x, scalar, modulus);
});
#endif
}

void multiply_poly_scalar_coeffmod(
Expand Down
10 changes: 10 additions & 0 deletions native/src/seal/util/polyarithsmallmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@ namespace seal
throw std::invalid_argument("modulus");
}
#endif

#ifdef SEAL_USE_INTEL_HEXL
intel::hexl::EltwiseReduceMod(result, poly, coeff_count, modulus.value(), 0, 1);
#else
SEAL_ITERATE(
iter(poly, result), coeff_count, [&](auto I) { get<1>(I) = barrett_reduce_64(get<0>(I), modulus); });
#endif
}

inline void modulo_poly_coeffs(
Expand Down Expand Up @@ -314,7 +319,11 @@ namespace seal
throw std::invalid_argument("result");
}
#endif

const uint64_t modulus_value = modulus.value();
#ifdef SEAL_USE_INTEL_HEXL
intel::hexl::EltwiseSubMod(result, operand1, operand2, coeff_count, modulus_value);
#else
SEAL_ITERATE(iter(operand1, operand2, result), coeff_count, [&](auto I) {
#ifdef SEAL_DEBUG
if (get<0>(I) >= modulus_value)
Expand All @@ -330,6 +339,7 @@ namespace seal
std::int64_t borrow = sub_uint64(get<0>(I), get<1>(I), &temp_result);
get<2>(I) = temp_result + (modulus_value & static_cast<std::uint64_t>(-borrow));
});
#endif
}

inline void sub_poly_coeffmod(
Expand Down
6 changes: 6 additions & 0 deletions native/tests/seal/modulus.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ namespace sealtest
stringstream stream;

Modulus mod;
#ifdef SEAL_USE_ZLIB
compr_mode_type compr_mode = compr_mode_type::zlib;
#elif defined(SEAL_USE_ZSTD)
compr_mode_type compr_mode = compr_mode_type::zstd;
#else
compr_mode_type compr_mode = compr_mode_type::none;
#endif
mod.save(stream, compr_mode);

Modulus mod2;
Expand Down
8 changes: 6 additions & 2 deletions native/tests/seal/serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,15 @@ namespace sealtest
Serialization::SEALHeader header;
ASSERT_TRUE(Serialization::IsValidHeader(header));

header.compr_mode = (compr_mode_type)0x01;
#ifdef SEAL_USE_ZLIB
header.compr_mode = compr_mode_type::zlib;
ASSERT_TRUE(Serialization::IsValidHeader(header));
#endif

header.compr_mode = (compr_mode_type)0x02;
#ifdef SEAL_USE_ZSTD
compr_mode_type compr_mode = compr_mode_type::zstd;
ASSERT_TRUE(Serialization::IsValidHeader(header));
#endif

Serialization::SEALHeader invalid_header;
invalid_header.magic = 0x1212;
Expand Down