decode.c (8929B)
1 /* See LICENSE for license details. */ 2 #define LIB_FN function 3 #include "ogl_beamformer_lib.c" 4 5 #include <signal.h> 6 #include <stdarg.h> 7 #include <stdio.h> 8 #include <stdlib.h> 9 10 #define AVERAGE_SAMPLES countof(((BeamformerComputeStatsTable *)0)->times) 11 //#define RF_TIME_SAMPLES 2432 12 #define RF_TIME_SAMPLES 4096 13 14 read_only global u32 decode_transmit_counts[] = { 15 2, 4, 8, 12, 16, 20, 24, 32, 40, 48, 64, 80, 96, 128, 160, 192, 256 16 }; 17 18 typedef struct { 19 b32 loop; 20 b32 once; 21 b32 dump; 22 b32 full_aperture; 23 24 u32 warmup_count; 25 26 char *outdir; 27 28 char **remaining; 29 i32 remaining_count; 30 } Options; 31 32 global b32 g_should_exit; 33 34 #define die(...) die_((char *)__func__, __VA_ARGS__) 35 function no_return void 36 die_(char *function_name, char *format, ...) 37 { 38 if (function_name) 39 fprintf(stderr, "%s: ", function_name); 40 41 va_list ap; 42 43 va_start(ap, format); 44 vfprintf(stderr, format, ap); 45 va_end(ap); 46 47 os_exit(1); 48 } 49 50 #if OS_LINUX 51 52 function void 53 os_make_directory(char *name) 54 { 55 mkdir(name, 0770); 56 } 57 58 #elif OS_WINDOWS 59 60 W32(b32) CreateDirectoryA(c8 *, void *); 61 62 function void 63 os_make_directory(char *name) 64 { 65 CreateDirectoryA(name, 0); 66 } 67 68 #else 69 #error Unsupported Platform 70 #endif 71 72 #define shift_n(v, c, n) v += n, c -= n 73 #define shift(v, c) shift_n(v, c, 1) 74 #define unshift(v, c) shift_n(v, c, -1) 75 76 function void 77 usage(char *argv0) 78 { 79 die("%s [--loop] [--once] [--full-aperture] [--warmup n] [--dump dir]\n" 80 " --loop: reupload data forever\n" 81 " --once: only run a single frame\n" 82 " --full-aperture: recieve on full 256 channel aperture\n" 83 " --warmup: warmup with n runs\n" 84 " --dump: dump output stats files to dir\n", 85 argv0); 86 } 87 88 function Options 89 parse_argv(i32 argc, char *argv[]) 90 { 91 Options result = {0}; 92 93 char *argv0 = argv[0]; 94 shift(argv, argc); 95 96 while (argc > 0) { 97 s8 arg = c_str_to_s8(*argv); 98 shift(argv, argc); 99 100 if (s8_equal(arg, s8("--loop"))) { 101 result.loop = 1; 102 } else if (s8_equal(arg, s8("--full-aperture"))) { 103 result.full_aperture = 1; 104 } else if (s8_equal(arg, s8("--dump"))) { 105 if (argc) { 106 result.outdir = *argv; 107 result.dump = 1; 108 shift(argv, argc); 109 } else { 110 die("expected directory to dump to\n"); 111 } 112 } else if (s8_equal(arg, s8("--once"))) { 113 result.once = 1; 114 } else if (s8_equal(arg, s8("--warmup"))) { 115 if (argc) { 116 result.warmup_count = (u32)atoi(*argv); 117 shift(argv, argc); 118 } 119 } else if (arg.len > 0 && arg.data[0] == '-') { 120 usage(argv0); 121 } else { 122 unshift(argv, argc); 123 break; 124 } 125 } 126 127 result.remaining = argv; 128 result.remaining_count = argc; 129 130 return result; 131 } 132 133 function b32 134 send_frame(i16 *restrict i16_data, u32 data_size) 135 { 136 b32 result = beamformer_push_data_with_compute(i16_data, data_size, BeamformerViewPlaneTag_XZ, 0); 137 if (!result && !g_should_exit) printf("lib error: %s\n", beamformer_get_last_error_string()); 138 return result; 139 } 140 141 function uv4 142 decoded_data_dim(u32 transmit_count, b32 full_aperture) 143 { 144 u32 max_transmits = decode_transmit_counts[countof(decode_transmit_counts) - 1]; 145 uv4 result = {{RF_TIME_SAMPLES, full_aperture? max_transmits: transmit_count, transmit_count, 1}}; 146 return result; 147 } 148 149 function uv2 150 raw_data_dim(u32 transmit_count, b32 full_aperture) 151 { 152 uv4 dec = decoded_data_dim(transmit_count, full_aperture); 153 uv2 result = {{dec.x * transmit_count, 256}}; 154 return result; 155 } 156 157 function u32 158 data_size_for_transmit_count(u32 transmit_count, b32 full_aperture) 159 { 160 uv2 rf_dim = raw_data_dim(transmit_count, full_aperture); 161 u32 result = rf_dim.x * rf_dim.y * sizeof(i16); 162 return result; 163 } 164 165 function i16 * 166 generate_test_data_for_transmit_count(u32 transmit_count, b32 full_aperture) 167 { 168 uz rf_size = data_size_for_transmit_count(transmit_count, full_aperture); 169 i16 *result = malloc(rf_size); 170 if (!result) die("malloc\n"); 171 return result; 172 } 173 174 function void 175 dump_stats(BeamformerComputeStatsTable *stats, Options *options, u32 transmit_count) 176 { 177 char path_buffer[1024]; 178 Stream sb = {.data = (u8 *)path_buffer, .cap = sizeof(path_buffer)}; 179 stream_append_s8s(&sb, c_str_to_s8(options->outdir), s8(OS_PATH_SEPARATOR), s8("decode_")); 180 stream_append_u64(&sb, transmit_count); 181 stream_append_s8(&sb, s8(".bin")); 182 stream_append_byte(&sb, 0); 183 os_write_new_file(path_buffer, (s8){.len = sizeof(*stats), .data = (u8 *)stats}); 184 } 185 186 function void 187 send_parameters(Options *options, u32 transmit_count) 188 { 189 BeamformerParameters bp = {0}; 190 bp.decode_mode = BeamformerDecodeMode_Hadamard; 191 b32 full_aperture = options->full_aperture; 192 uv3 dec_data_dim = decoded_data_dim(transmit_count, full_aperture).xyz; 193 bp.sample_count = dec_data_dim.x; 194 bp.channel_count = dec_data_dim.y; 195 bp.acquisition_count = dec_data_dim.z; 196 197 bp.raw_data_dimensions = raw_data_dim(transmit_count, full_aperture); 198 beamformer_push_parameters(&bp); 199 200 /* NOTE(rnp): use real channel mapping so that we still get ~random~ access pattern */ 201 read_only local_persist i16 channel_mapping[] = { 202 217, 129, 212, 188, 255, 131, 237, 190, 241, 130, 248, 187, 219, 128, 218, 181, 203 216, 134, 247, 180, 220, 132, 238, 178, 246, 133, 240, 179, 221, 135, 239, 173, 204 231, 137, 211, 172, 222, 139, 213, 170, 249, 138, 210, 171, 223, 136, 232, 189, 205 233, 142, 209, 164, 224, 140, 214, 186, 254, 141, 208, 163, 225, 143, 215, 185, 206 230, 145, 204, 162, 226, 147, 206, 165, 229, 146, 207, 161, 227, 144, 205, 182, 207 234, 150, 203, 160, 228, 148, 201, 166, 236, 149, 200, 159, 235, 175, 202, 177, 208 242, 151, 196, 191, 243, 155, 198, 167, 245, 154, 199, 158, 244, 176, 197, 174, 209 250, 168, 195, 184, 251, 156, 193, 152, 253, 153, 192, 157, 252, 183, 194, 169, 210 102, 62, 71, 3, 100, 60, 82, 1, 78, 61, 72, 4, 64, 63, 101, 10, 211 103, 57, 107, 11, 99, 59, 81, 13, 73, 58, 79, 12, 98, 56, 80, 18, 212 88, 54, 108, 19, 97, 52, 106, 21, 70, 53, 109, 20, 96, 55, 87, 2, 213 86, 49, 110, 27, 95, 51, 105, 5, 65, 50, 111, 28, 94, 48, 104, 6, 214 89, 46, 115, 29, 93, 44, 113, 26, 90, 45, 112, 30, 92, 47, 114, 9, 215 85, 41, 116, 31, 91, 43, 118, 25, 83, 42, 119, 32, 84, 16, 117, 14, 216 77, 40, 123, 0, 76, 36, 121, 24, 74, 37, 120, 33, 75, 15, 122, 17, 217 69, 23, 124, 7, 68, 35, 126, 39, 66, 38, 127, 34, 67, 8, 125, 22, 218 }; 219 beamformer_push_channel_mapping(channel_mapping, countof(channel_mapping)); 220 221 i32 shader_stages = BeamformerShaderKind_Decode; 222 beamformer_push_pipeline(&shader_stages, 1, BeamformerDataKind_Int16); 223 beamformer_set_global_timeout(1000); 224 } 225 226 function f32 227 execute_study(Options *options, u32 transmit_count, i16 *restrict data) 228 { 229 send_parameters(options, transmit_count); 230 u32 data_size = data_size_for_transmit_count(transmit_count, options->full_aperture); 231 for (u32 i = 0; !g_should_exit && i < options->warmup_count; i++) 232 send_frame(data, data_size); 233 234 u64 start = os_timer_count(); 235 f64 frequency = os_timer_frequency(); 236 for (u32 i = 0; !g_should_exit && i < AVERAGE_SAMPLES; i++) 237 send_frame(data, data_size); 238 f32 result = (os_timer_count() - start) / frequency / (f32)AVERAGE_SAMPLES; 239 240 return result; 241 } 242 243 function void 244 print_result(u32 transmit_count, f32 time) 245 { 246 printf("decode %3u | %uF Average: %8.3f [ms]\n", transmit_count, (u32)AVERAGE_SAMPLES, time * 1e3); 247 } 248 249 function void 250 sigint(i32 _signo) 251 { 252 g_should_exit = 1; 253 } 254 255 extern i32 256 main(i32 argc, char *argv[]) 257 { 258 Options options = parse_argv(argc, argv); 259 260 if (options.remaining_count) 261 usage(argv[0]); 262 263 if (options.dump) os_make_directory(options.outdir); 264 265 signal(SIGINT, sigint); 266 267 BeamformerLiveImagingParameters lip = {.active = 1, .save_enabled = 1}; 268 s8 short_name = s8("Decode Bench"); 269 mem_copy(lip.save_name_tag, short_name.data, (uz)short_name.len); 270 lip.save_name_tag_length = (i32)short_name.len; 271 beamformer_set_live_parameters(&lip); 272 273 u32 max_transmit_count = decode_transmit_counts[countof(decode_transmit_counts) - 1]; 274 i16 *data = generate_test_data_for_transmit_count(max_transmit_count, options.full_aperture); 275 if (options.loop) { 276 for (;!g_should_exit;) { 277 u32 transmit_count = decode_transmit_counts[0]; 278 f32 time = execute_study(&options, transmit_count, data); 279 if (!g_should_exit) print_result(transmit_count, time); 280 } 281 } else if (options.once) { 282 u32 transmit_count = decode_transmit_counts[0]; 283 u32 data_size = data_size_for_transmit_count(transmit_count, options.full_aperture); 284 send_parameters(&options, transmit_count); 285 send_frame(data, data_size); 286 } else { 287 BeamformerComputeStatsTable stats = {0}; 288 for (iz i = 0; i < countof(decode_transmit_counts); i++) { 289 u32 transmit_count = decode_transmit_counts[i]; 290 f32 time = execute_study(&options, transmit_count, data); 291 if (options.dump) { 292 beamformer_compute_timings(&stats, 1000); 293 dump_stats(&stats, &options, transmit_count); 294 } 295 if (!g_should_exit) print_result(transmit_count, time); 296 } 297 } 298 299 lip.active = 0; 300 beamformer_set_live_parameters(&lip); 301 302 return 0; 303 }