feat(cpp): use cxx (was cbindgen) and mv interface in a workspace

This commit is contained in:
Mayeul@Zama
2022-04-13 09:26:30 +02:00
committed by rudy-6-4
parent 8f3cb77d95
commit fee5b10b0e
14 changed files with 243 additions and 5 deletions

View File

@@ -32,8 +32,6 @@ jobs:
- name: Formatting
run: cargo fmt --check
# For some reason doing the build explicitely before make it available for both clippy and test
# But clippy and test alone do not share the build
- name: Build
run: cargo build --all-targets
@@ -41,4 +39,6 @@ jobs:
run: cargo clippy --all-targets
- name: Tests
run: cargo test --no-fail-fast --all-targets
run: |
cargo test --no-fail-fast --all-targets
make -C concrete-optimizer-cpp test-ci

View File

@@ -3,5 +3,6 @@
members = [
"concrete-optimizer",
"v0-parameters",
"concrete-optimizer-cpp"
]

1
concrete-optimizer-cpp/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
tests/tests_exe

View File

@@ -0,0 +1,17 @@
[package]
# see https://doc.rust-lang.org/cargo/reference/manifest.html
name = "concrete-optimizer-cpp"
version = "0.1.0"
authors = [""]
edition = "2021"
[dependencies]
cxx = "1.0"
concrete-optimizer = {path = "../concrete-optimizer" }
[build-dependencies]
cxx-build = "1.0"
[lib]
path = "src/concrete-optimizer.rs"
crate-type = ["staticlib"]

View File

@@ -0,0 +1,41 @@
# dev or release
CARGO_PROFILE ?= release
# debug or release
PROFILE_SUBDIR ?= release
ROOT = ..
TARGET_DIR = $(ROOT)/target
PROFILE_DIR = $(TARGET_DIR)/$(PROFILE_SUBDIR)
CXXBRIDGE_DIR = $(TARGET_DIR)/cxxbridge/concrete-optimizer-cpp/src
INTERFACE_LIB = $(TARGET_DIR)/libconcrete_optimizer_cpp.a
INTERFACE_HEADER = src/cpp/concrete-optimizer.hpp
INTERFACE_CPP = src/cpp/concrete-optimizer.cpp
INTERFACE_SOURCES = $(INTERFACE_HEADER) $(INTERFACE_CPP)
SOURCES = $(shell find $(ROOT)/concrete-optimizer/src) \
$(shell find $(ROOT)/concrete-optimizer-cpp/src -name '*.rs')
TESTS_SOURCES = tests/src/main.cpp
TEST_DEP_LIBS = -l pthread -ldl
$(INTERFACE_SOURCES) $(INTERFACE_LIB): $(SOURCES)
cd $(ROOT) && cargo build -p concrete-optimizer-cpp --profile $(CARGO_PROFILE)
cp $(CXXBRIDGE_DIR)/concrete-optimizer.rs.h $(INTERFACE_HEADER)
cp $(CXXBRIDGE_DIR)/concrete-optimizer.rs.cc $(INTERFACE_CPP)
cp $(PROFILE_DIR)/libconcrete_optimizer_cpp.a $(TARGET_DIR)
tests/tests_exe: $(INTERFACE_SOURCES) $(INTERFACE_LIB) $(TESTS_SOURCES)
g++ -o $@ $(TESTS_SOURCES) $(INTERFACE_CPP) $(INTERFACE_LIB) -I $(shell dirname $(INTERFACE_HEADER)) $(TEST_DEP_LIBS)
chmod +x $@
build: $(INTERFACE_SOURCES) $(INTERFACE_LIB)
test: tests/tests_exe
./tests/tests_exe
test-ci:
$(MAKE) CARGO_PROFILE=dev PROFILE_SUBDIR=debug test
git diff --check src/cpp || echo Please commit the new version of generated files
clean:
rm -f $(INTERFACE_LIB) tests/tests_exe

View File

@@ -0,0 +1,5 @@
fn main() {
let _build = cxx_build::bridge("src/concrete-optimizer.rs");
println!("cargo:rerun-if-changed=src/lib.rs");
}

View File

@@ -0,0 +1,16 @@
# In your project CMakeLists.txt:
# 1. define the path containing concrete-optimizer repository, builded.
# CONCRETE_OPTIMIZER_DIR
# 2. add lines:
# add_subdirectory(${CONCRETE_OPTIMIZER_DIR}/concrete-optimizer-cpp/cmake-utils)
# include_directories(${CONCRETE_OPTIMIZER_DIR}/concrete-optimizer-cpp/src/cpp)
add_library(concrete_optimizer STATIC ${CONCRETE_OPTIMIZER_DIR}/concrete-optimizer-cpp/src/cpp/concrete-optimizer.cpp)
target_link_libraries(concrete_optimizer PRIVATE
pthread m dl
"${CONCRETE_OPTIMIZER_DIR}/target/libconcrete_optimizer_cpp.a"
)
install(TARGETS concrete_optimizer EXPORT concrete_optimizer)
install(EXPORT concrete_optimizer DESTINATION "./")

View File

@@ -0,0 +1,80 @@
fn no_solution() -> ffi::Solution {
ffi::Solution {
p_error: 1.0, // error probability to signal an impossible solution
..ffi::Solution::default()
}
}
fn optimise_bootstrap(
precision: u64,
security_level: u64,
noise_factor: f64,
maximum_acceptable_error_probability: f64,
) -> ffi::Solution {
use concrete_optimizer::global_parameters::DEFAUT_DOMAINS;
let sum_size = 1;
let glwe_log_polynomial_sizes = DEFAUT_DOMAINS
.glwe_pbs_constrained
.log2_polynomial_size
.as_vec();
let glwe_dimensions = DEFAUT_DOMAINS.glwe_pbs_constrained.glwe_dimension.as_vec();
let internal_lwe_dimensions = DEFAUT_DOMAINS.free_glwe.glwe_dimension.as_vec();
let result = concrete_optimizer::optimisation::atomic_pattern::optimise_one::<u64>(
sum_size,
precision,
security_level,
noise_factor,
maximum_acceptable_error_probability,
&glwe_log_polynomial_sizes,
&glwe_dimensions,
&internal_lwe_dimensions,
None,
);
result.best_solution.map_or_else(no_solution, |a| a.into())
}
impl From<concrete_optimizer::optimisation::atomic_pattern::Solution> for ffi::Solution {
fn from(a: concrete_optimizer::optimisation::atomic_pattern::Solution) -> Self {
Self {
input_lwe_dimension: a.input_lwe_dimension,
internal_ks_output_lwe_dimension: a.internal_ks_output_lwe_dimension,
ks_decomposition_level_count: a.ks_decomposition_level_count,
ks_decomposition_base_log: a.ks_decomposition_base_log,
glwe_polynomial_size: a.glwe_polynomial_size,
glwe_dimension: a.glwe_dimension,
br_decomposition_level_count: a.br_decomposition_level_count,
br_decomposition_base_log: a.br_decomposition_base_log,
complexity: a.complexity,
noise_max: a.noise_max,
p_error: a.p_error,
}
}
}
#[cxx::bridge]
mod ffi {
#[namespace = "concrete_optimizer"]
extern "Rust" {
fn optimise_bootstrap(
precision: u64,
security_level: u64,
noise_factor: f64,
maximum_acceptable_error_probability: f64,
) -> Solution;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Solution {
pub input_lwe_dimension: u64, //n_big
pub internal_ks_output_lwe_dimension: u64, //n_small
pub ks_decomposition_level_count: u64, //l(KS)
pub ks_decomposition_base_log: u64, //b(KS)
pub glwe_polynomial_size: u64, //N
pub glwe_dimension: u64, //k
pub br_decomposition_level_count: u64, //l(BR)
pub br_decomposition_base_log: u64, //b(BR)
pub complexity: f64,
pub noise_max: f64,
pub p_error: f64, // error probability
}
}

View File

@@ -0,0 +1,33 @@
#include <cstdint>
#include <type_traits>
struct Solution;
#ifndef CXXBRIDGE1_STRUCT_Solution
#define CXXBRIDGE1_STRUCT_Solution
struct Solution final {
::std::uint64_t input_lwe_dimension;
::std::uint64_t internal_ks_output_lwe_dimension;
::std::uint64_t ks_decomposition_level_count;
::std::uint64_t ks_decomposition_base_log;
::std::uint64_t glwe_polynomial_size;
::std::uint64_t glwe_dimension;
::std::uint64_t br_decomposition_level_count;
::std::uint64_t br_decomposition_base_log;
double complexity;
double noise_max;
double p_error;
using IsRelocatable = ::std::true_type;
};
#endif // CXXBRIDGE1_STRUCT_Solution
namespace concrete_optimizer {
extern "C" {
::Solution concrete_optimizer$cxxbridge1$optimise_bootstrap(::std::uint64_t precision, ::std::uint64_t security_level, double noise_factor, double maximum_acceptable_error_probability) noexcept;
} // extern "C"
::Solution optimise_bootstrap(::std::uint64_t precision, ::std::uint64_t security_level, double noise_factor, double maximum_acceptable_error_probability) noexcept {
return concrete_optimizer$cxxbridge1$optimise_bootstrap(precision, security_level, noise_factor, maximum_acceptable_error_probability);
}
} // namespace concrete_optimizer

View File

@@ -0,0 +1,28 @@
#pragma once
#include <cstdint>
#include <type_traits>
struct Solution;
#ifndef CXXBRIDGE1_STRUCT_Solution
#define CXXBRIDGE1_STRUCT_Solution
struct Solution final {
::std::uint64_t input_lwe_dimension;
::std::uint64_t internal_ks_output_lwe_dimension;
::std::uint64_t ks_decomposition_level_count;
::std::uint64_t ks_decomposition_base_log;
::std::uint64_t glwe_polynomial_size;
::std::uint64_t glwe_dimension;
::std::uint64_t br_decomposition_level_count;
::std::uint64_t br_decomposition_base_log;
double complexity;
double noise_max;
double p_error;
using IsRelocatable = ::std::true_type;
};
#endif // CXXBRIDGE1_STRUCT_Solution
namespace concrete_optimizer {
::Solution optimise_bootstrap(::std::uint64_t precision, ::std::uint64_t security_level, double noise_factor, double maximum_acceptable_error_probability) noexcept;
} // namespace concrete_optimizer

View File

@@ -0,0 +1,11 @@
#include "concrete-optimizer.hpp"
int main(int argc, char *argv[]) {
auto solution = concrete_optimizer::optimise_bootstrap(1, 128, 1, .05);
if (solution.glwe_polynomial_size != 1024) {
return 1;
}
return 0;
}

View File

@@ -14,7 +14,7 @@ statrs = "0.15.0"
approx = "0.5"
[build-dependencies]
cbindgen = "0.20.0"
cbindgen = "0.23.0"
[lib]
crate-type= [

View File

@@ -40,6 +40,11 @@ impl AtomicPatternDag {
extra_data: (),
})
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.operators.len()
}
}
#[cfg(test)]

View File

@@ -1,2 +1,2 @@
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Weight(pub(crate) u32);
pub struct Weight(pub u64);