Browse Source

big: Improve timing code.

Jeroen van Rijn 4 years ago
parent
commit
511057ca36
2 changed files with 53 additions and 48 deletions
  1. 42 22
      core/math/big/example.odin
  2. 11 26
      core/math/big/helpers.odin

+ 42 - 22
core/math/big/example.odin

@@ -45,34 +45,53 @@ _SQR_TOOM_CUTOFF,
 print_timings :: proc() {
 print_timings :: proc() {
 	fmt.printf("Timings:\n");
 	fmt.printf("Timings:\n");
 	for v, i in Timings {
 	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;
 			avg_s: string;
 			switch {
 			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:
 			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;
 			total_s: string;
 			switch {
 			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:
 			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 {
 Category :: enum {
 	itoa,
 	itoa,
 	atoi,
 	atoi,
@@ -83,16 +102,16 @@ Category :: enum {
 	ctz,
 	ctz,
 	bitfield_extract,
 	bitfield_extract,
 };
 };
+
 Event :: struct {
 Event :: struct {
-	t: time.Duration,
-	c: int,
+	ticks:  time.Duration,
+	count:  int,
+	cycles: u64,
 }
 }
 Timings := [Category]Event{};
 Timings := [Category]Event{};
 
 
 print :: proc(name: string, a: ^Int, base := i8(10), print_name := true, newline := true, print_extra_info := false) {
 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);
 	as, err := itoa(a, base);
-	Timings[.itoa].t += time.tick_since(s); Timings[.itoa].c += 1;
 
 
 	defer delete(as);
 	defer delete(as);
 	cb, _ := count_bits(a);
 	cb, _ := count_bits(a);
@@ -128,12 +147,13 @@ demo :: proc() {
 	/*
 	/*
 		Timing loop
 		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);
 	fmt.printf("be1: %v\n", be1);
 }
 }
 
 

+ 11 - 26
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 {
 	if count == 1 {
 		limb := offset / _DIGIT_BITS;
 		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)));
 		i := _WORD(1 << _WORD((offset % _DIGIT_BITS)));
 		return 1 if ((_WORD(a.digit[limb]) & i) != 0) else 0, nil;
 		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.
 		There are 3 possible cases.
 		-	[offset:][:count] covers 1 DIGIT,
 		-	[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,
 		-	[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
 				e.g. offset:  0, count: 120 = bits 0..59, 60..119
 		-	[offset:][:count] covers 3 DIGITS,
 		-	[offset:][:count] covers 3 DIGITS,
 				e.g. offset: 40, count: 100 = bits 40..59, 0..59, 0..19
 				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);
 	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;
 	bits_left -= num_bits;
 	if bits_left == 0 { return res, nil; }
 	if bits_left == 0 { return res, nil; }
 
 
 	res_shift := num_bits;
 	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;
 	bits_left -= num_bits;
 	if bits_left == 0 { return res, nil; }
 	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;
 	mask     = (1 << uint(bits_left)) - 1;
 	res_shift += _DIGIT_BITS;
 	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;
 	return res, nil;
 }
 }