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

Fix field arithmetic benchmark cairo related bug + perf #518

Merged
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ docsite/
cairo-vm-env
cairo-vm
tmp/
profile.json

# we dont need compiled cairo programs in repo
/cairo_programs/*.json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from starkware.cairo.common.cairo_builtins import BitwiseBuiltin
from starkware.cairo.common.bool import TRUE
from uint384 import u384, Uint384
from uint384_extension import u384_ext
from field_arithmetic import field_arithmetic
from cairo_programs.uint384 import u384, Uint384
from cairo_programs.uint384_extension import u384_ext
from cairo_programs.field_arithmetic import field_arithmetic

func run_get_square{range_check_ptr, bitwise_ptr: BitwiseBuiltin*}(
prime: Uint384, generator: Uint384, num: Uint384, iterations: felt
Expand Down
11 changes: 6 additions & 5 deletions scripts/benchmarks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@
set -e
. ../cairo-vm-env/bin/activate

BENCH_DIR=../cairo_programs/benchmarks
CAIRO_DIR=../cairo_programs/
CAIRO_VM_CLI=../cairo-vm/target/release/cairo-vm-cli
ZIG_CLI=../zig-out/bin/ziggy-starkdust
cd ..
BENCH_DIR=cairo_programs/benchmarks
CAIRO_DIR=cairo_programs/
CAIRO_VM_CLI=cairo-vm/target/release/cairo-vm-cli
ZIG_CLI=zig-out/bin/ziggy-starkdust

for file in $(ls ${BENCH_DIR} | grep .cairo | sed -E 's/\.cairo//'); do
echo "Compiling ${file} program..."
cairo-compile --cairo_path="${CAIRO_DIR}" ${BENCH_DIR}/${file}.cairo --output ${BENCH_DIR}/${file}.json --proof_mode
cairo-compile --cairo_path="${CAIRO_DIR}:../${CAIRO_DIR}" ${BENCH_DIR}/${file}.cairo --output ${BENCH_DIR}/${file}.json --proof_mode
echo "Running ${file} benchmark"
hyperfine --show-output --warmup 2 \
-n "cairo-vm (Rust)" "${CAIRO_VM_CLI} ${BENCH_DIR}/${file}.json --memory_file /dev/null --trace_file /dev/null --layout all_cairo" \
Expand Down
11 changes: 9 additions & 2 deletions scripts/build_cairo_programs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ set -e

cd ..
CAIRO_PROGRAMS_DIR=cairo_programs
CAIRO_PROGRAMS_BENCHMARK_DIR=cairo_programs/benchmarks
CAIRO_DIR=cairo_programs

for file in $(ls ${CAIRO_PROGRAMS_DIR} | grep .cairo | sed -E 's/\.cairo//'); do
echo "Compiling benchmark cairo programs"
for file in $(ls ${CAIRO_PROGRAMS_BENCHMARK_DIR} | grep .cairo | sed -E 's/\.cairo//'); do
echo "Compiling ${file} program..."
cairo-compile --cairo_path="${CAIRO_DIR}:" ${CAIRO_PROGRAMS_DIR}/${file}.cairo --output ${CAIRO_PROGRAMS_DIR}/${file}.json --proof_mode
cairo-compile --cairo_path="${CAIRO_DIR}:../${CAIRO_DIR}" ${CAIRO_PROGRAMS_BENCHMARK_DIR}/${file}.cairo --output ${CAIRO_PROGRAMS_BENCHMARK_DIR}/${file}.json --proof_mode
done

echo "Compiling cairo programs"
for file in $(ls ${CAIRO_PROGRAMS_DIR} | grep .cairo | sed -E 's/\.cairo//'); do
echo "Compiling ${file} program..."
cairo-compile --cairo_path="${CAIRO_DIR}:../${CAIRO_DIR}" ${CAIRO_PROGRAMS_DIR}/${file}.cairo --output ${CAIRO_PROGRAMS_DIR}/${file}.json --proof_mode
done
1 change: 1 addition & 0 deletions src/hint_processor/field_arithmetic.zig
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ pub fn bigIntIntGetSquareRoot(
(try field_helper.sqrtPrimePower(allocator, gx, p)) orelse try Int.initSet(allocator, 0)
else
try Int.initSet(allocator, 0);

defer root_gx.deinit();

if (!x.eqlZero() and (@intFromBool(success_x) ^ @intFromBool(success_gx)) == 0)
Expand Down
6 changes: 5 additions & 1 deletion src/hint_processor/hint_utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ pub fn getConstantFromVarName(
var it = constants.iterator();
while (it.next()) |k| {
if (k.key_ptr.*.len < var_name.len) continue;
if (std.mem.eql(u8, var_name, k.key_ptr.*[k.key_ptr.*.len - var_name.len ..]))
var iter =
std.mem.splitBackwardsSequence(u8, k.key_ptr.*, ".");

const v = iter.next() orelse continue;
if (std.mem.eql(u8, var_name, v))
return k.value_ptr.*;
}

Expand Down
11 changes: 3 additions & 8 deletions src/hint_processor/uint256_utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -255,15 +255,10 @@ pub fn split64(
ap_tracking: ApTracking,
) !void {
const a = try hint_utils.getIntegerFromVarName("a", vm, ids_data, ap_tracking);
const digits = a.toLeDigits();
var bytes = [_]u8{0} ** 32;
const numb = a.toU256();

inline for (1..4) |i| {
std.mem.writeInt(u64, bytes[(i - 1) * 8 .. i * 8], digits[i], .little);
}

const low = Felt252.fromInt(u64, digits[0]);
const high = Felt252.fromBytesLe(bytes);
const low = Felt252.fromInt(u256, numb & ((1 << 64) - 1));
const high = Felt252.fromInt(u256, numb >> 64);

try hint_utils.insertValueFromVarName(allocator, "high", MaybeRelocatable.fromFelt(high), vm, ids_data, ap_tracking);
try hint_utils.insertValueFromVarName(allocator, "low", MaybeRelocatable.fromFelt(low), vm, ids_data, ap_tracking);
Expand Down
12 changes: 7 additions & 5 deletions src/hint_processor/uint384.zig
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,15 @@ pub fn uint384Split128(
ids_data: std.StringHashMap(HintReference),
ap_tracking: ApTracking,
) !void {
const bound = Felt252.pow2Const(128);
const a = try hint_utils.getIntegerFromVarName("a", vm, ids_data, ap_tracking);

const high, const low = a.divRem(bound);
const number = a.toU256();

try hint_utils.insertValueFromVarName(allocator, "low", MaybeRelocatable.fromFelt(low), vm, ids_data, ap_tracking);
try hint_utils.insertValueFromVarName(allocator, "high", MaybeRelocatable.fromFelt(high), vm, ids_data, ap_tracking);
const low = number & ((1 << 128) - 1);
const high = number >> 128;

try hint_utils.insertValueFromVarName(allocator, "low", MaybeRelocatable.fromInt(u256, low), vm, ids_data, ap_tracking);
try hint_utils.insertValueFromVarName(allocator, "high", MaybeRelocatable.fromInt(u256, high), vm, ids_data, ap_tracking);
}

// Implements Hint:
Expand Down Expand Up @@ -129,7 +131,7 @@ pub fn addNoUint384Check(
var buffer: [20]u8 = undefined;

inline for (0..3) |i| {
var sum = try a.limbs[i].toInt(u258) + try b.limbs[i].toInt(u258);
var sum = try a.limbs[i].toInt(u512) + try b.limbs[i].toInt(u512);

if (prev_carry) sum += 1;

Expand Down
6 changes: 3 additions & 3 deletions src/vm/core.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1407,11 +1407,11 @@ pub const OperandsResult = struct {
/// The second operand value.
op_1: MaybeRelocatable = undefined,
/// The relocatable address of the destination operand.
dst_addr: Relocatable = .{},
dst_addr: Relocatable = undefined,
/// The relocatable address of the first operand.
op_0_addr: Relocatable = .{},
op_0_addr: Relocatable = undefined,
/// The relocatable address of the second operand.
op_1_addr: Relocatable = .{},
op_1_addr: Relocatable = undefined,
/// Indicator for deduced operands.
deduced_operands: u8 = 0,

Expand Down
15 changes: 6 additions & 9 deletions src/vm/memory/memory.zig
Original file line number Diff line number Diff line change
Expand Up @@ -442,15 +442,12 @@ pub const Memory = struct {
// TODO: rewrite all on self rel address
// Return null if either the segment index or offset is not valid.
// Otherwise, return the maybe_relocatable value at the specified address.
return if (data.items[segment_index].items[address.offset].getValue()) |val|
switch (val) {
.relocatable => |addr| self.relAddress(
addr,
) catch unreachable,
else => |_| val,
}
else
null;
return switch (data.items[segment_index].items[address.offset].getValue() orelse return null) {
.relocatable => |addr| self.relAddress(
addr,
) catch unreachable,
else => |v| v,
};
}

/// Retrieves a `Felt252` value from the memory at the specified relocatable address.
Expand Down
20 changes: 20 additions & 0 deletions src/vm/memory/relocatable.zig
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,26 @@ pub const MaybeRelocatable = union(enum) {
relocatable: Relocatable,
felt: Felt252,

/// This method is interface method, when format is calling for this struct, this method is called
///
pub fn format(
self: Self,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
switch (self) {
.relocatable => |r| {
try writer.print("MaybeRelocatable(Relocatable(offset={},index={}))", .{ r.offset, r.segment_index });
},
.felt => |f| {
try writer.print("MaybeRelocatable(Felt({}))", .{f.toU256()});
},
}
}

/// Determines if two `MaybeRelocatable` instances are equal.
///
/// This method compares the variant type and the contained value. If both the variant
Expand Down
Loading