Files
icicle/examples/c++/msm/example.cpp
2024-07-28 14:49:02 +03:00

102 lines
3.7 KiB
C++

#include <fstream>
#include <iostream>
#include <iomanip>
#include "icicle/runtime.h"
#include "icicle/api/bn254.h"
using namespace bn254;
#include "examples_utils.h"
int main(int argc, char* argv[])
{
try_load_and_set_backend_device(argc, argv);
std::cout << "\nIcicle example: Muli-Scalar Multiplication (MSM)" << std::endl;
std::cout << "Example parameters" << std::endl;
int batch_size = 1;
unsigned msm_size = 1 << 10;
int N = batch_size * msm_size;
std::cout << "Batch size: " << batch_size << std::endl;
std::cout << "MSM size: " << msm_size << std::endl;
std::cout << "\nPart I: use G1 points" << std::endl;
std::cout << "Generating random inputs on-host" << std::endl;
auto scalars = std::make_unique<scalar_t[]>(N);
auto points = std::make_unique<affine_t[]>(N);
projective_t result;
scalar_t::rand_host_many(scalars.get(), N);
projective_t::rand_host_many(points.get(), N);
std::cout << "Using default MSM configuration with on-host inputs" << std::endl;
auto config = default_msm_config();
config.batch_size = batch_size;
std::cout << "\nRunning MSM kernel with on-host inputs" << std::endl;
// Execute the MSM kernel
START_TIMER(MSM_host_mem);
ICICLE_CHECK(bn254_msm(scalars.get(), points.get(), msm_size, config, &result));
END_TIMER(MSM_host_mem, "MSM from host-memory took");
std::cout << projective_t::to_affine(result) << std::endl;
DeviceProperties device_props;
ICICLE_CHECK(icicle_get_device_properties(device_props));
// If device does not share memory with host, copy inputs explicitly and execute msm with device pointers
if (!device_props.using_host_memory) {
std::cout << "\nReconfiguring MSM to use on-device inputs" << std::endl;
config.are_results_on_device = true;
config.are_scalars_on_device = true;
config.are_points_on_device = true;
std::cout << "Copying inputs to-device" << std::endl;
scalar_t* scalars_d;
affine_t* points_d;
projective_t* result_d;
ICICLE_CHECK(icicle_malloc((void**)&scalars_d, sizeof(scalar_t) * N));
ICICLE_CHECK(icicle_malloc((void**)&points_d, sizeof(affine_t) * N));
ICICLE_CHECK(icicle_malloc((void**)&result_d, sizeof(projective_t)));
ICICLE_CHECK(icicle_copy(scalars_d, scalars.get(), sizeof(scalar_t) * N));
ICICLE_CHECK(icicle_copy(points_d, points.get(), sizeof(affine_t) * N));
std::cout << "Running MSM kernel with on-device inputs" << std::endl;
// Execute the MSM kernel
START_TIMER(MSM_device_mem);
ICICLE_CHECK(msm(scalars_d, points_d, msm_size, config, result_d));
END_TIMER(MSM_device_mem, "MSM from device-memory took");
// Copy the result back to the host
icicle_copy(&result, result_d, sizeof(projective_t));
// Print the result
std::cout << projective_t::to_affine(result) << std::endl;
// Free the device memory
icicle_free(scalars_d);
icicle_free(points_d);
icicle_free(result_d);
}
std::cout << "\nPart II: use G2 points" << std::endl;
std::cout << "Generating random inputs on-host" << std::endl;
// use the same scalars
auto g2_points = std::make_unique<g2_affine_t[]>(N);
g2_projective_t::rand_host_many(g2_points.get(), N);
std::cout << "Reconfiguring MSM to use on-host inputs" << std::endl;
config.are_results_on_device = false;
config.are_scalars_on_device = false;
config.are_points_on_device = false;
g2_projective_t g2_result;
START_TIMER(MSM_g2);
ICICLE_CHECK(bn254_g2_msm(scalars.get(), g2_points.get(), msm_size, config, &g2_result));
END_TIMER(MSM_g2, "MSM G2 from host-memory took");
std::cout << g2_projective_t::to_affine(g2_result) << std::endl;
// Similar to G1 MSM, can explicitly copy to device and execute the G2 MSM using device pointers
return 0;
}