From 857f757932a0960ec786bc1337a6b3f0a1ddea95 Mon Sep 17 00:00:00 2001 From: batzor <32958247+batzor@users.noreply.github.com> Date: Thu, 29 Aug 2024 17:01:46 +0900 Subject: [PATCH] test(benchmark): add fri benchmark --- Cargo.Bazel.lock | 81 ++++++++++- Cargo.lock | 19 +++ Cargo.toml | 1 + WORKSPACE | 1 + benchmark/fri/BUILD.bazel | 63 +++++++++ benchmark/fri/README.md | 48 +++++++ benchmark/fri/fri_benchmark.cc | 158 ++++++++++++++++++++++ benchmark/fri/fri_benchmark_mac_m3.png | Bin 0 -> 17670 bytes benchmark/fri/fri_benchmark_ubuntu_i9.png | Bin 0 -> 16809 bytes benchmark/fri/fri_config.cc | 56 ++++++++ benchmark/fri/fri_config.h | 40 ++++++ benchmark/fri/fri_runner.h | 92 +++++++++++++ benchmark/fri/plonky3/BUILD.bazel | 13 ++ benchmark/fri/plonky3/Cargo.toml | 31 +++++ benchmark/fri/plonky3/src/lib.rs | 142 +++++++++++++++++++ 15 files changed, 744 insertions(+), 1 deletion(-) create mode 100644 benchmark/fri/BUILD.bazel create mode 100644 benchmark/fri/README.md create mode 100644 benchmark/fri/fri_benchmark.cc create mode 100644 benchmark/fri/fri_benchmark_mac_m3.png create mode 100644 benchmark/fri/fri_benchmark_ubuntu_i9.png create mode 100644 benchmark/fri/fri_config.cc create mode 100644 benchmark/fri/fri_config.h create mode 100644 benchmark/fri/fri_runner.h create mode 100644 benchmark/fri/plonky3/BUILD.bazel create mode 100644 benchmark/fri/plonky3/Cargo.toml create mode 100644 benchmark/fri/plonky3/src/lib.rs diff --git a/Cargo.Bazel.lock b/Cargo.Bazel.lock index 6eb764bf4..4fd106195 100644 --- a/Cargo.Bazel.lock +++ b/Cargo.Bazel.lock @@ -1,5 +1,5 @@ { - "checksum": "493a31da6b3ac2a5605ba241c05d083f25487a1fdd2efcb09d582c8b3be8cba9", + "checksum": "0196cd729d17db7cf65b8594500ed8e7a9f294853aac594160ae042741599e75", "crates": { "addchain 0.2.0": { "name": "addchain", @@ -12952,6 +12952,84 @@ }, "license": "MIT OR Apache-2.0" }, + "plonky3_fri_benchmark 0.0.1": { + "name": "plonky3_fri_benchmark", + "version": "0.0.1", + "repository": null, + "targets": [ + { + "Library": { + "crate_name": "plonky3_fri_benchmark", + "crate_root": "src/lib.rs", + "srcs": [ + "**/*.rs" + ] + } + } + ], + "library_target_name": "plonky3_fri_benchmark", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "p3-baby-bear 0.1.3-succinct", + "target": "p3_baby_bear" + }, + { + "id": "p3-challenger 0.1.3-succinct", + "target": "p3_challenger" + }, + { + "id": "p3-commit 0.1.3-succinct", + "target": "p3_commit" + }, + { + "id": "p3-dft 0.1.3-succinct", + "target": "p3_dft" + }, + { + "id": "p3-field 0.1.3-succinct", + "target": "p3_field" + }, + { + "id": "p3-fri 0.1.3-succinct", + "target": "p3_fri" + }, + { + "id": "p3-matrix 0.1.3-succinct", + "target": "p3_matrix" + }, + { + "id": "p3-merkle-tree 0.1.3-succinct", + "target": "p3_merkle_tree" + }, + { + "id": "p3-poseidon2 0.1.3-succinct", + "target": "p3_poseidon2" + }, + { + "id": "p3-symmetric 0.1.3-succinct", + "target": "p3_symmetric" + }, + { + "id": "p3-util 0.1.3-succinct", + "target": "p3_util" + }, + { + "id": "zkhash 0.2.0", + "target": "zkhash" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.0.1" + }, + "license": "MIT OR Apache-2.0" + }, "plonky3_poseidon2_benchmark 0.0.1": { "name": "plonky3_poseidon2_benchmark", "version": "0.0.1", @@ -21549,6 +21627,7 @@ "halo2_msm_benchmark 0.0.1": "benchmark/msm/halo2", "horizen_poseidon2_benchmark 0.0.1": "benchmark/poseidon2/horizen", "plonky3_batch_fft_benchmark 0.0.1": "benchmark/fft_batch/plonky3", + "plonky3_fri_benchmark 0.0.1": "benchmark/fri/plonky3", "plonky3_poseidon2_benchmark 0.0.1": "benchmark/poseidon2/plonky3", "tachyon_plonky3 0.0.1": "vendors/plonky3", "tachyon_rs 0.0.1": "tachyon/rs", diff --git a/Cargo.lock b/Cargo.lock index 3c2aa8214..2e86e81e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2509,6 +2509,25 @@ dependencies = [ "tachyon_rs", ] +[[package]] +name = "plonky3_fri_benchmark" +version = "0.0.1" +dependencies = [ + "p3-baby-bear", + "p3-challenger", + "p3-commit", + "p3-dft", + "p3-field", + "p3-fri", + "p3-matrix", + "p3-merkle-tree", + "p3-poseidon2", + "p3-symmetric", + "p3-util", + "tachyon_rs", + "zkhash 0.2.0 (git+https://github.com/HorizenLabs/poseidon2.git?rev=bb476b9)", +] + [[package]] name = "plonky3_poseidon2_benchmark" version = "0.0.1" diff --git a/Cargo.toml b/Cargo.toml index cd6e937b9..571e41dad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "benchmark/fft/bellman", "benchmark/fft/halo2", "benchmark/fft_batch/plonky3", + "benchmark/fri/plonky3", "benchmark/poseidon/arkworks", "benchmark/poseidon2/horizen", "benchmark/poseidon2/plonky3", diff --git a/WORKSPACE b/WORKSPACE index dda3518e9..8aefd0dd6 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -58,6 +58,7 @@ crates_repository( "//benchmark/fft/bellman:Cargo.toml", "//benchmark/fft/halo2:Cargo.toml", "//benchmark/fft_batch/plonky3:Cargo.toml", + "//benchmark/fri/plonky3:Cargo.toml", "//benchmark/poseidon/arkworks:Cargo.toml", "//benchmark/poseidon2/horizen:Cargo.toml", "//benchmark/poseidon2/plonky3:Cargo.toml", diff --git a/benchmark/fri/BUILD.bazel b/benchmark/fri/BUILD.bazel new file mode 100644 index 000000000..f96aeda53 --- /dev/null +++ b/benchmark/fri/BUILD.bazel @@ -0,0 +1,63 @@ +load( + "//bazel:tachyon_cc.bzl", + "tachyon_cc_binary", + "tachyon_cc_library", +) + +tachyon_cc_library( + name = "fri_config", + testonly = True, + srcs = ["fri_config.cc"], + hdrs = ["fri_config.h"], + deps = [ + "//benchmark:config", + "//tachyon/base/console", + "//tachyon/base/containers:container_util", + ], +) + +tachyon_cc_library( + name = "fri_runner", + testonly = True, + hdrs = ["fri_runner.h"], + deps = [ + ":fri_config", + "//benchmark:simple_reporter", + "//tachyon/base/containers:container_util", + "//tachyon/base/time", + "//tachyon/c/math/matrix", + "//tachyon/crypto/hashes/sponge/poseidon2:poseidon2_horizen_external_matrix", + "//tachyon/math/matrix:matrix_types", + ], +) + +tachyon_cc_binary( + name = "fri_benchmark", + testonly = True, + srcs = ["fri_benchmark.cc"], + deps = [ + ":fri_config", + ":fri_runner", + "//benchmark:simple_reporter", + "//benchmark/fri/plonky3", + "//tachyon/base:profiler", + "//tachyon/c/math/finite_fields/baby_bear", + "//tachyon/crypto/challenger:duplex_challenger", + "//tachyon/crypto/commitments/fri:fri_config", + "//tachyon/crypto/commitments/fri:two_adic_fri", + "//tachyon/crypto/commitments/fri:two_adic_multiplicative_coset", + "//tachyon/crypto/commitments/merkle_tree/field_merkle_tree:extension_field_merkle_tree_mmcs", + "//tachyon/crypto/commitments/merkle_tree/field_merkle_tree:field_merkle_tree_mmcs", + "//tachyon/crypto/hashes/sponge:padding_free_sponge", + "//tachyon/crypto/hashes/sponge:truncated_permutation", + "//tachyon/crypto/hashes/sponge/poseidon2", + "//tachyon/crypto/hashes/sponge/poseidon2:poseidon2_horizen_external_matrix", + "//tachyon/math/finite_fields:packed_field_traits_forward", + "//tachyon/math/finite_fields/baby_bear:baby_bear4", + "//tachyon/math/finite_fields/baby_bear:packed_baby_bear4", + "//tachyon/math/finite_fields/baby_bear:poseidon2", + "//tachyon/math/matrix:matrix_types", + "//tachyon/math/polynomials/univariate:radix2_evaluation_domain", + "@com_google_absl//absl/strings", + ], +) diff --git a/benchmark/fri/README.md b/benchmark/fri/README.md new file mode 100644 index 000000000..a2eeae3ed --- /dev/null +++ b/benchmark/fri/README.md @@ -0,0 +1,48 @@ +# Fri PCS Benchmark + +## CPU + +```bash +Run on 13th Gen Intel(R) Core(TM) i9-13900K (32 X 5500 MHz CPU s) +CPU Caches: + L1 Data 48 KiB (x16) + L1 Instruction 32 KiB (x16) + L2 Unified 2048 KiB (x16) + L3 Unified 36864 KiB (x1) + +Run on Apple M3 Pro (12 X 4050 MHz) +CPU Caches: + L1 Data 64 KiB (x12) + L1 Instruction 128 KiB (x12) + L2 Unified 4096 KiB (x12) +``` + +```shell +bazel run -c opt --//:has_openmp --//:has_rtti --//:has_matplotlib //benchmark/fri:fri_benchmark -- -k 18 -k 19 -k 20 -k 21 -k 22 --batch_size 100 --input_num 4 --log_blowup 2 --vendor plonky3 --check_results +``` + +## On Intel i9-13900K + +| Exponent | Tachyon | Plonky3 | +| :------- | ----------- | -------- | +| 18 | **2.27057** | 2.54643 | +| 19 | **3.82310** | 5.18472 | +| 20 | **6.57053** | 10.2886 | +| 21 | **11.6738** | 20.8495 | +| 22 | **23.3768** | 43.0323 | + +![image](/benchmark/fri/fri_benchmark_ubuntu_i9.png) + +## On Mac M3 Pro + +WARNING: On Mac M3, high degree tests are not feasible due to memory constraints. + +| Exponent | Tachyon | Plonky3 | +| :------- | ------- | ------------ | +| 18 | 3.68509 | **1.39107** | +| 19 | 7.37079 | **2.76483** | +| 20 | 14.9081 | **5.62375** | +| 21 | 30.3153 | **11.8295** | +| 22 | 64.8022 | **25.4490** | + +![image](/benchmark/fri/fri_benchmark_mac_m3.png) diff --git a/benchmark/fri/fri_benchmark.cc b/benchmark/fri/fri_benchmark.cc new file mode 100644 index 000000000..faa54c98b --- /dev/null +++ b/benchmark/fri/fri_benchmark.cc @@ -0,0 +1,158 @@ +#include + +#include "absl/strings/substitute.h" + +// clang-format off +#include "benchmark/simple_reporter.h" +#include "benchmark/fri/fri_config.h" +#include "benchmark/fri/fri_runner.h" +// clang-format on +#include "tachyon/base/profiler.h" +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear_type_traits.h" +#include "tachyon/crypto/challenger/duplex_challenger.h" +#include "tachyon/crypto/commitments/fri/fri_config.h" +#include "tachyon/crypto/commitments/fri/two_adic_fri.h" +#include "tachyon/crypto/commitments/fri/two_adic_multiplicative_coset.h" +#include "tachyon/crypto/commitments/merkle_tree/field_merkle_tree/extension_field_merkle_tree_mmcs.h" +#include "tachyon/crypto/commitments/merkle_tree/field_merkle_tree/field_merkle_tree_mmcs.h" +#include "tachyon/crypto/hashes/sponge/padding_free_sponge.h" +#include "tachyon/crypto/hashes/sponge/poseidon2/poseidon2.h" +#include "tachyon/crypto/hashes/sponge/poseidon2/poseidon2_horizen_external_matrix.h" +#include "tachyon/crypto/hashes/sponge/truncated_permutation.h" +#include "tachyon/math/finite_fields/baby_bear/baby_bear4.h" +#include "tachyon/math/finite_fields/baby_bear/packed_baby_bear4.h" +#include "tachyon/math/finite_fields/baby_bear/poseidon2.h" +#include "tachyon/math/matrix/matrix_types.h" +#include "tachyon/math/polynomials/univariate/radix2_evaluation_domain.h" + +namespace tachyon::benchmark { + +extern "C" tachyon_baby_bear* run_fri_pcs_plonky3_baby_bear( + const tachyon_baby_bear* data, const size_t* raw_degrees, + size_t num_of_degrees, size_t batch_size, uint32_t log_blowup, + uint64_t* duration); + +template +void CheckResult(bool check_results, const Commitment& tachyon_result, + const Commitment& vendor_result) { + if (check_results) { + CHECK_EQ(tachyon_result, vendor_result) << "Results not matched"; + } +} + +void Run(const FRIConfig& config) { + constexpr size_t kRate = 8; + constexpr size_t kChunk = 8; + constexpr size_t kN = 2; + + using F = math::BabyBear; + using ExtF = math::BabyBear4; + using PackedF = math::PackedBabyBear; + using ExtendedPackedF = math::PackedBabyBear4; + using Poseidon2 = crypto::Poseidon2Sponge>>; + using PackedPoseidon2 = + crypto::Poseidon2Sponge>>; + using MyHasher = crypto::PaddingFreeSponge; + using MyPackedHasher = + crypto::PaddingFreeSponge; + using MyCompressor = crypto::TruncatedPermutation; + using MyPackedCompressor = + crypto::TruncatedPermutation; + using MMCS = crypto::FieldMerkleTreeMMCS; + using ExtMMCS = + crypto::FieldMerkleTreeMMCS; + using ChallengeMMCS = crypto::ExtensionFieldMerkleTreeMMCS; + using Challenger = crypto::DuplexChallenger; + using MyPcs = crypto::TwoAdicFRI; + + PackedF::Init(); + ExtendedPackedF::Init(); + + crypto::Poseidon2Config poseidon2_config = + crypto::Poseidon2Config::CreateCustom( + 15, 7, 8, 13, math::GetPoseidon2BabyBearInternalShiftVector<15>()); + Poseidon2 sponge(poseidon2_config); + MyHasher hasher(sponge); + MyCompressor compressor(sponge); + + crypto::Poseidon2Config packed_config = + crypto::Poseidon2Config::CreateCustom( + 15, 7, 8, 13, math::GetPoseidon2BabyBearInternalShiftVector<15>()); + PackedPoseidon2 packed_sponge(packed_config); + MyPackedHasher packed_hasher(packed_sponge); + MyPackedCompressor packed_compressor(std::move(packed_sponge)); + MMCS mmcs(hasher, packed_hasher, compressor, packed_compressor); + + ChallengeMMCS challenge_mmcs( + ExtMMCS(std::move(hasher), std::move(packed_hasher), + std::move(compressor), std::move(packed_compressor))); + + crypto::FRIConfig fri_config{config.log_blowup(), 10, 8, + challenge_mmcs}; + MyPcs pcs = MyPcs(std::move(mmcs), std::move(fri_config)); + + SimpleReporter reporter; + std::string name; + name = absl::Substitute("FRI Benchmark (b: $0, l: $1)", config.batch_size(), + config.log_blowup()); + reporter.set_title(name); + reporter.set_x_label("Max Exponent"); + reporter.set_column_labels(base::Map( + config.exponents(), + [](uint32_t exponent) { return base::NumberToString(exponent); })); + + FRIRunner runner(reporter, config, pcs); + + std::vector degrees = config.GetDegrees(); + + reporter.AddVendor(Vendor::Tachyon()); + for (Vendor vendor : config.vendors()) { + reporter.AddVendor(vendor); + } + + for (size_t degree : degrees) { + math::RowMajorMatrix input = + math::RowMajorMatrix::Random(degree, config.batch_size()); + + F tachyon_commit = runner.Run(Vendor::Tachyon(), input); + for (Vendor vendor : config.vendors()) { + if (vendor.value() == Vendor::kPlonky3) { + F vendor_commit = + runner.RunExternal(vendor, run_fri_pcs_plonky3_baby_bear, input); + CheckResult(config.check_results(), tachyon_commit, vendor_commit); + } else { + NOTREACHED(); + } + } + } + + reporter.Show(); +} + +int RealMain(int argc, char** argv) { + base::FilePath tmp_file; + CHECK(base::GetTempDir(&tmp_file)); + tmp_file = tmp_file.Append("fri_benchmark.perfetto-trace"); + base::Profiler profiler({tmp_file}); + + profiler.Init(); + profiler.Start(); + + FRIConfig config; + if (!config.Parse(argc, argv)) { + return 1; + } + + Run(config); + return 0; +} + +} // namespace tachyon::benchmark + +int main(int argc, char** argv) { + return tachyon::benchmark::RealMain(argc, argv); +} diff --git a/benchmark/fri/fri_benchmark_mac_m3.png b/benchmark/fri/fri_benchmark_mac_m3.png new file mode 100644 index 0000000000000000000000000000000000000000..1065aaf2b23a8e431602b88ba98bffebb8e740d2 GIT binary patch literal 17670 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 literal 0 HcmV?d00001 diff --git a/benchmark/fri/fri_benchmark_ubuntu_i9.png b/benchmark/fri/fri_benchmark_ubuntu_i9.png new file mode 100644 index 0000000000000000000000000000000000000000..3a89a2f7315e21fb108034bf77e7cf82c967e9fb GIT binary patch literal 16809 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 literal 0 HcmV?d00001 diff --git a/benchmark/fri/fri_config.cc b/benchmark/fri/fri_config.cc new file mode 100644 index 000000000..fe1dc364e --- /dev/null +++ b/benchmark/fri/fri_config.cc @@ -0,0 +1,56 @@ +#include "benchmark/fri/fri_config.h" + +#include + +#include "tachyon/base/console/iostream.h" +#include "tachyon/base/containers/container_util.h" + +namespace tachyon::benchmark { + +FRIConfig::FRIConfig() { + parser_.AddFlag>>(&exponents_) + .set_short_name("-k") + .set_required() + .set_help( + "Specify the exponent 'k's where the degree of poly to test is 2ᵏ."); + parser_.AddFlag>(&batch_size_) + .set_short_name("-b") + .set_long_name("--batch_size") + .set_default_value(100) + .set_help("Specify the batch size. By default, 100."); + parser_.AddFlag>(&input_num_) + .set_short_name("-i") + .set_long_name("--input_num") + .set_default_value(4) + .set_help( + "Specify the number of inputs in a single round. By default, 4."); + parser_.AddFlag>(&log_blowup_) + .set_short_name("-l") + .set_long_name("--log_blowup") + .set_default_value(1) + .set_help("Specify the log blowup. By default, 1."); + parser_.AddFlag>>(&vendors_) + .set_long_name("--vendor") + .set_help("Vendors to be benchmarked with. (supported vendors: plonky3"); +} + +void FRIConfig::PostParse() { + base::ranges::sort(exponents_); // NOLINT(build/include_what_you_use) +} + +std::vector FRIConfig::GetDegrees() const { + return base::Map(exponents_, + [](uint32_t exponent) { return (size_t{1} << exponent); }); +} + +bool FRIConfig::Validate() const { + for (const Vendor vendor : vendors_) { + if (vendor.value() != Vendor::kPlonky3) { + tachyon_cerr << "Unsupported vendor " << vendor.ToString() << std::endl; + return false; + } + } + return true; +} + +} // namespace tachyon::benchmark diff --git a/benchmark/fri/fri_config.h b/benchmark/fri/fri_config.h new file mode 100644 index 000000000..b89b7a22e --- /dev/null +++ b/benchmark/fri/fri_config.h @@ -0,0 +1,40 @@ +#ifndef BENCHMARK_FRI_FRI_CONFIG_H_ +#define BENCHMARK_FRI_FRI_CONFIG_H_ + +#include + +#include + +// clang-format off +#include "benchmark/config.h" +// clang-format on + +namespace tachyon::benchmark { + +class FRIConfig : public Config { + public: + FRIConfig(); + FRIConfig(const FRIConfig& other) = delete; + FRIConfig& operator=(const FRIConfig& other) = delete; + + const std::vector& exponents() const { return exponents_; } + size_t batch_size() const { return batch_size_; } + size_t input_num() const { return input_num_; } + uint32_t log_blowup() const { return log_blowup_; } + + std::vector GetDegrees() const; + + private: + // Config methods + void PostParse() override; + bool Validate() const override; + + std::vector exponents_; + size_t batch_size_; + size_t input_num_; + uint32_t log_blowup_; +}; + +} // namespace tachyon::benchmark + +#endif // BENCHMARK_FRI_FRI_CONFIG_H_ diff --git a/benchmark/fri/fri_runner.h b/benchmark/fri/fri_runner.h new file mode 100644 index 000000000..442406904 --- /dev/null +++ b/benchmark/fri/fri_runner.h @@ -0,0 +1,92 @@ +#ifndef BENCHMARK_FRI_FRI_RUNNER_H_ +#define BENCHMARK_FRI_FRI_RUNNER_H_ + +#include +#include + +#include +#include +#include + +// clang-format off +#include "benchmark/fri/fri_config.h" +#include "benchmark/simple_reporter.h" +// clang-format on +#include "tachyon/base/time/time.h" +#include "tachyon/c/math/finite_fields/baby_bear/baby_bear_type_traits.h" +#include "tachyon/crypto/commitments/fri/two_adic_multiplicative_coset.h" +#include "tachyon/math/matrix/matrix_types.h" + +namespace tachyon::benchmark { + +template +class FRIRunner { + public: + using F = typename PCS::F; + using Domain = crypto::TwoAdicMultiplicativeCoset; + + typedef tachyon_baby_bear* (*ExternalFn)(const tachyon_baby_bear* data, + const size_t* degrees, + size_t num_of_degrees, + size_t batch_size, + uint32_t log_blowup, + uint64_t* duration); + + FRIRunner(SimpleReporter& reporter, const FRIConfig& config, PCS& pcs) + : reporter_(reporter), config_(config), pcs_(pcs) {} + + F Run(Vendor vendor, const math::RowMajorMatrix& input) { + size_t max_degree = static_cast(input.rows()); + std::vector degrees; + for (size_t d = max_degree >> (config_.input_num() - 1); d <= max_degree; + d <<= 1) { + degrees.push_back(d); + } + + std::vector> inner_polys = + base::Map(degrees, [this, input](size_t degree) { + math::RowMajorMatrix ret = + Eigen::Map>( + &input.data()[0], degree, config_.batch_size()); + return ret; + }); + + std::vector inner_domains = + base::Map(degrees, [this](size_t degree) { + return this->pcs_.GetNaturalDomainForDegree(degree); + }); + + base::TimeTicks start = base::TimeTicks::Now(); + typename PCS::Commitment commit; + typename PCS::ProverData prover_data; + CHECK(pcs_.Commit(inner_domains, inner_polys, &commit, &prover_data)); + reporter_.AddTime(vendor, base::TimeTicks::Now() - start); + return static_cast>(commit)[1]; + } + + F RunExternal(Vendor vendor, ExternalFn fn, + const math::RowMajorMatrix& input) { + size_t max_degree = static_cast(input.rows()); + std::vector degrees; + for (size_t d = max_degree >> (config_.input_num() - 1); d <= max_degree; + d <<= 1) { + degrees.push_back(d); + } + + uint64_t duration_in_us = 0; + tachyon_baby_bear* data = + fn(c::base::c_cast(input.data()), °rees[0], degrees.size(), + config_.batch_size(), config_.log_blowup(), &duration_in_us); + reporter_.AddTime(vendor, base::Microseconds(duration_in_us)); + return c::base::native_cast(data)[1]; + } + + private: + SimpleReporter& reporter_; + const FRIConfig& config_; + PCS& pcs_; +}; + +} // namespace tachyon::benchmark + +#endif // BENCHMARK_FRI_FRI_RUNNER_H_ diff --git a/benchmark/fri/plonky3/BUILD.bazel b/benchmark/fri/plonky3/BUILD.bazel new file mode 100644 index 000000000..0152e05a6 --- /dev/null +++ b/benchmark/fri/plonky3/BUILD.bazel @@ -0,0 +1,13 @@ +load("@crate_index//:defs.bzl", "aliases", "all_crate_deps") +load("//bazel:tachyon_rust.bzl", "tachyon_rust_static_library") + +tachyon_rust_static_library( + name = "plonky3", + srcs = glob(["src/**/*.rs"]), + aliases = aliases(), + proc_macro_deps = all_crate_deps(proc_macro = True), + visibility = ["//benchmark/fri:__pkg__"], + deps = all_crate_deps(normal = True) + [ + "//tachyon/rs:tachyon_rs", + ], +) diff --git a/benchmark/fri/plonky3/Cargo.toml b/benchmark/fri/plonky3/Cargo.toml new file mode 100644 index 000000000..fd7e53867 --- /dev/null +++ b/benchmark/fri/plonky3/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "plonky3_fri_benchmark" +version = "0.0.1" +authors = ["The Tachyon Authors "] +edition = "2021" +description = """ +Plonky3 Fri Benchmark +""" +license = "MIT OR Apache-2.0" +repository = "https://github.com/kroma-network/tachyon" +readme = "README.md" +categories = ["cryptography"] +keywords = ["tachyon", "benchmark", "plonky3"] +publish = false + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +p3-baby-bear = "0.1.3-succinct" +p3-challenger = "0.1.3-succinct" +p3-commit = "0.1.3-succinct" +p3-dft = "0.1.3-succinct" +p3-field = "0.1.3-succinct" +p3-fri = "0.1.3-succinct" +p3-matrix = "0.1.3-succinct" +p3-merkle-tree = "0.1.3-succinct" +p3-poseidon2 = "0.1.3-succinct" +p3-symmetric = "0.1.3-succinct" +p3-util = "0.1.3-succinct" +tachyon_rs = { path = "../../../tachyon/rs" } +zkhash = { git = "https://github.com/HorizenLabs/poseidon2.git", rev = "bb476b9" } diff --git a/benchmark/fri/plonky3/src/lib.rs b/benchmark/fri/plonky3/src/lib.rs new file mode 100644 index 000000000..8359da356 --- /dev/null +++ b/benchmark/fri/plonky3/src/lib.rs @@ -0,0 +1,142 @@ +use std::fmt::Debug; +use std::time::Instant; + +use p3_baby_bear::{BabyBear, DiffusionMatrixBabyBear}; +use p3_challenger::{CanObserve, DuplexChallenger, FieldChallenger}; +use p3_commit::{ExtensionMmcs, Pcs, PolynomialSpace}; +use p3_dft::Radix2DitParallel; +use p3_field::extension::BinomialExtensionField; +use p3_field::{AbstractField, ExtensionField, Field}; +use p3_fri::{FriConfig, TwoAdicFriPcs}; +use p3_matrix::dense::RowMajorMatrix; +use p3_merkle_tree::FieldMerkleTreeMmcs; +use p3_poseidon2::{Poseidon2, Poseidon2ExternalMatrixHL}; +use p3_symmetric::{PaddingFreeSponge, TruncatedPermutation}; +use p3_util::log2_strict_usize; + +use tachyon_rs::math::finite_fields::baby_bear::BabyBear as CppBabyBear; +use zkhash::ark_ff::PrimeField as ark_PrimeField; +use zkhash::poseidon2::poseidon2_instance_babybear::RC16 as BabyBearRC16; + +type Val = BabyBear; +type Challenge = BinomialExtensionField; + +type Perm = Poseidon2; +type MyHash = PaddingFreeSponge; +type MyCompress = TruncatedPermutation; + +type ValMmcs = + FieldMerkleTreeMmcs<::Packing, ::Packing, MyHash, MyCompress, 8>; +type ChallengeMmcs = ExtensionMmcs; + +type Dft = Radix2DitParallel; +type Challenger = DuplexChallenger; +type MyPcs = TwoAdicFriPcs; + +fn get_perm(rounds_f: usize, rounds_p: usize) -> Perm { + let mut round_constants: Vec<[BabyBear; 16]> = BabyBearRC16 + .iter() + .map(|vec| { + vec.iter() + .cloned() + .map(|ark_ff| BabyBear::from_canonical_u32(ark_ff.into_bigint().0[0] as u32)) + .collect::>() + .try_into() + .unwrap() + }) + .collect(); + let internal_start = rounds_f / 2; + let internal_end = (rounds_f / 2) + rounds_p; + let internal_round_constants = round_constants + .drain(internal_start..internal_end) + .map(|vec| vec[0]) + .collect::>(); + let external_round_constants = round_constants; + + Perm::new( + rounds_f, + external_round_constants, + Poseidon2ExternalMatrixHL, + rounds_p, + internal_round_constants, + DiffusionMatrixBabyBear, + ) +} + +fn get_pcs(log_blowup: usize, log_n: usize) -> (MyPcs, Challenger) { + let perm = get_perm(8, 13); + + let hash = MyHash::new(perm.clone()); + let compress = MyCompress::new(perm.clone()); + + let val_mmcs = ValMmcs::new(hash, compress); + let challenge_mmcs = ChallengeMmcs::new(val_mmcs.clone()); + + let fri_config = FriConfig { + log_blowup, + num_queries: 10, + proof_of_work_bits: 8, + mmcs: challenge_mmcs, + }; + + let pcs = MyPcs::new(log_n, Dft {}, val_mmcs, fri_config); + (pcs, Challenger::new(perm.clone())) +} + +fn do_test_fri_pcs( + (pcs, _challenger): &(P, Challenger), + degrees: Vec, + data: Vec>, + duration: *mut u64, +) -> *mut CppBabyBear +where + P: Pcs, + P::Domain: PolynomialSpace, + Val: Field, + Challenge: ExtensionField, + Challenger: Clone + CanObserve + FieldChallenger, +

>::Commitment: Debug, +{ + let domains: Vec<_> = degrees + .iter() + .map(|°ree| pcs.natural_domain_for_degree(degree)) + .collect(); + let domains_and_polys: Vec<(P::Domain, RowMajorMatrix)> = + domains.into_iter().zip(data.into_iter()).collect(); + + let start = Instant::now(); + let (commit, _data) = pcs.commit(domains_and_polys); + unsafe { + duration.write(start.elapsed().as_micros() as u64); + } + Box::into_raw(Box::new(commit)) as *mut CppBabyBear +} + +#[no_mangle] +pub extern "C" fn run_fri_pcs_plonky3_baby_bear( + data: *const BabyBear, + raw_degrees: *const usize, + num_of_degrees: usize, + batch_size: usize, + log_blowup: u32, + duration: *mut u64, +) -> *mut CppBabyBear { + let degrees = + unsafe { std::slice::from_raw_parts(raw_degrees as *mut usize, num_of_degrees).to_vec() }; + + let (pcs, challenger) = get_pcs( + log_blowup as usize, + log2_strict_usize(*degrees.last().unwrap()), + ); + + let polys: Vec> = degrees + .iter() + .map(|°ree| { + let size = degree * batch_size; + let values: Vec = + unsafe { std::slice::from_raw_parts(data as *mut BabyBear, size).to_vec() }; + RowMajorMatrix::::new(values, batch_size) + }) + .collect(); + do_test_fri_pcs(&(pcs, challenger), degrees, polys, duration) +}