From 511057ca364bdadde4d6752769b93f33a799497e Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Thu, 5 Aug 2021 13:44:07 +0200 Subject: [PATCH] big: Improve timing code. --- core/math/big/example.odin | 64 +++++++++++++++++++++++++------------- core/math/big/helpers.odin | 37 +++++++--------------- 2 files changed, 53 insertions(+), 48 deletions(-) diff --git a/core/math/big/example.odin b/core/math/big/example.odin index f0d70b0c4..d46ce5e9d 100644 --- a/core/math/big/example.odin +++ b/core/math/big/example.odin @@ -45,34 +45,53 @@ _SQR_TOOM_CUTOFF, print_timings :: proc() { fmt.printf("Timings:\n"); for v, i in Timings { - if v.c > 0 { - avg := time.Duration(f64(v.t) / f64(v.c)); + if v.count > 0 { + avg_ticks := time.Duration(f64(v.ticks) / f64(v.count)); + avg_cycles := f64(v.cycles) / f64(v.count); avg_s: string; switch { - case avg < time.Microsecond: - avg_s = fmt.tprintf("%v ns", time.duration_nanoseconds(avg)); - case avg < time.Millisecond: - avg_s = fmt.tprintf("%v µs", time.duration_microseconds(avg)); + case avg_ticks < time.Microsecond: + avg_s = fmt.tprintf("%v ns / %v cycles", time.duration_nanoseconds(avg_ticks), avg_cycles); + case avg_ticks < time.Millisecond: + avg_s = fmt.tprintf("%v µs / %v cycles", time.duration_microseconds(avg_ticks), avg_cycles); case: - avg_s = fmt.tprintf("%v ms", time.duration_milliseconds(avg)); + avg_s = fmt.tprintf("%v ms / %v cycles", time.duration_milliseconds(avg_ticks), avg_cycles); } total_s: string; switch { - case v.t < time.Microsecond: - total_s = fmt.tprintf("%v ns", time.duration_nanoseconds(v.t)); - case v.t < time.Millisecond: - total_s = fmt.tprintf("%v µs", time.duration_microseconds(v.t)); + case v.ticks < time.Microsecond: + total_s = fmt.tprintf("%v ns / %v cycles", time.duration_nanoseconds(v.ticks), v.cycles); + case v.ticks < time.Millisecond: + total_s = fmt.tprintf("%v µs / %v cycles", time.duration_microseconds(v.ticks), v.cycles); case: - total_s = fmt.tprintf("%v ms", time.duration_milliseconds(v.t)); + total_s = fmt.tprintf("%v ms / %v cycles", time.duration_milliseconds(v.ticks), v.cycles); } - fmt.printf("\t%v: %s (avg), %s (total, %v calls)\n", i, avg_s, total_s, v.c); + fmt.printf("\t%v: %s (avg), %s (total, %v calls)\n", i, avg_s, total_s, v.count); } } } +@(deferred_in_out=_SCOPE_END) +SCOPED_TIMING :: #force_inline proc(c: Category) -> (ticks: time.Tick, cycles: u64) { + cycles = time.read_cycle_counter(); + ticks = time.tick_now(); + return; +} +_SCOPE_END :: #force_inline proc(c: Category, ticks: time.Tick, cycles: u64) { + cycles_now := time.read_cycle_counter(); + ticks_now := time.tick_now(); + + Timings[c].ticks = time.tick_diff(ticks, ticks_now); + Timings[c].cycles = cycles_now - cycles; + Timings[c].count += 1; +} +SCOPED_COUNT_ADD :: #force_inline proc(c: Category, count: int) { + Timings[c].count += count; +} + Category :: enum { itoa, atoi, @@ -83,16 +102,16 @@ Category :: enum { ctz, bitfield_extract, }; + Event :: struct { - t: time.Duration, - c: int, + ticks: time.Duration, + count: int, + cycles: u64, } Timings := [Category]Event{}; print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) { - s := time.tick_now(); as, err := itoa(a, base); - Timings[.itoa].t += time.tick_since(s); Timings[.itoa].c += 1; defer delete(as); cb, _ := count_bits(a); @@ -128,12 +147,13 @@ demo :: proc() { /* Timing loop */ - s_old := time.tick_now(); - for o := 0; o < count - bits; o += 1 { - be1, _ = int_bitfield_extract(a, o, bits); + { + SCOPED_TIMING(.bitfield_extract); + for o := 0; o < count - bits; o += 1 { + be1, _ = int_bitfield_extract(a, o, bits); + } } - Timings[.bitfield_extract].t += time.tick_since(s_old); - Timings[.bitfield_extract].c += (count - bits); + SCOPED_COUNT_ADD(.bitfield_extract, count - bits - 1); fmt.printf("be1: %v\n", be1); } diff --git a/core/math/big/helpers.odin b/core/math/big/helpers.odin index 435d82fe0..054b05abd 100644 --- a/core/math/big/helpers.odin +++ b/core/math/big/helpers.odin @@ -205,19 +205,19 @@ int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WORD, err: E */ if count == 1 { limb := offset / _DIGIT_BITS; - if limb < 0 || limb >= a.used { return 0, .Invalid_Argument; } + if limb < 0 || limb >= a.used { return 0, .Invalid_Argument; } i := _WORD(1 << _WORD((offset % _DIGIT_BITS))); return 1 if ((_WORD(a.digit[limb]) & i) != 0) else 0, nil; } - if count > _WORD_BITS || count < 1 { return 0, .Invalid_Argument; } + if count > _WORD_BITS || count < 1 { return 0, .Invalid_Argument; } /* There are 3 possible cases. - [offset:][:count] covers 1 DIGIT, - e.g. offset: 0, count: 60 = bits 0..59 + e.g. offset: 0, count: 60 = bits 0..59 - [offset:][:count] covers 2 DIGITS, - e.g. offset: 5, count: 60 = bits 5..59, 0..4 + e.g. offset: 5, count: 60 = bits 5..59, 0..4 e.g. offset: 0, count: 120 = bits 0..59, 60..119 - [offset:][:count] covers 3 DIGITS, e.g. offset: 40, count: 100 = bits 40..59, 0..59, 0..19 @@ -230,41 +230,26 @@ int_bitfield_extract :: proc(a: ^Int, offset, count: int) -> (res: _WORD, err: E num_bits := min(bits_left, _DIGIT_BITS - bits_offset); - // fmt.printf("offset: %v | count: %v\n\n", offset, count); - // fmt.printf("left: %v | bits_offset: %v | limb: %v | num: %v\n\n", bits_left, bits_offset, limb, num_bits); - - shift := offset % _DIGIT_BITS; - mask := (_WORD(1) << uint(num_bits)) - 1; - - // fmt.printf("shift: %v | mask: %v\n", shift, mask); - // fmt.printf("d: %v\n", a.digit[limb]); - - res = (_WORD(a.digit[limb]) >> uint(shift)) & mask; - - // fmt.printf("res: %v\n", res); + shift := offset % _DIGIT_BITS; + mask := (_WORD(1) << uint(num_bits)) - 1; + res = (_WORD(a.digit[limb]) >> uint(shift)) & mask; bits_left -= num_bits; if bits_left == 0 { return res, nil; } res_shift := num_bits; + num_bits = min(bits_left, _DIGIT_BITS); + mask = (1 << uint(num_bits)) - 1; - num_bits = min(bits_left, _DIGIT_BITS); - mask = (1 << uint(num_bits)) - 1; - - v := (_WORD(a.digit[limb + 1]) & mask) << uint(res_shift); - res |= v; + res |= (_WORD(a.digit[limb + 1]) & mask) << uint(res_shift); bits_left -= num_bits; if bits_left == 0 { return res, nil; } - // fmt.printf("bits_left: %v | offset: %v | num: %v\n", bits_left, offset, num_bits); - mask = (1 << uint(bits_left)) - 1; res_shift += _DIGIT_BITS; - v = (_WORD(a.digit[limb + 2]) & mask) << uint(res_shift); - res |= v; - + res |= (_WORD(a.digit[limb + 2]) & mask) << uint(res_shift); return res, nil; }