| 342 | #if MEGDNN_WITH_BENCHMARK |
| 343 | |
| 344 | void benchmark_nchw44_fp32(Handle* handle) { |
| 345 | using Param = param::Pooling; |
| 346 | auto run = [&](size_t n, size_t c, size_t h, size_t w, size_t filter, size_t stride, |
| 347 | size_t pad, Param::Mode mode) { |
| 348 | Param param; |
| 349 | param.window_h = param.window_w = filter; |
| 350 | param.stride_h = param.stride_w = stride; |
| 351 | param.pad_h = param.pad_w = pad; |
| 352 | param.format = Param::Format::NCHW; |
| 353 | param.mode = mode; |
| 354 | TensorShape nchw_shape = {n, c, h, w}; |
| 355 | TensorShape nchw44_shape = {n, c / 4, h, w, 4}; |
| 356 | TensorLayout dst_layout; |
| 357 | auto opr = handle->create_operator<Pooling>(); |
| 358 | opr->param() = param; |
| 359 | opr->deduce_layout({nchw_shape, dtype::Float32()}, dst_layout); |
| 360 | float calc_amount = |
| 361 | dst_layout.total_nr_elems() * param.window_h * param.window_w; |
| 362 | |
| 363 | Benchmarker<Pooling> benchmarker_float_nchw(handle); |
| 364 | Benchmarker<Pooling> benchmarker_float_nchw44(handle); |
| 365 | Benchmarker<Pooling> benchmarker_int_nchw44(handle); |
| 366 | size_t RUN = 500; |
| 367 | auto t1 = benchmarker_float_nchw.set_display(false) |
| 368 | .set_times(RUN) |
| 369 | .set_param(param) |
| 370 | .exec({nchw_shape, {}}); |
| 371 | |
| 372 | param.format = Param::Format::NCHW44; |
| 373 | auto t2 = benchmarker_int_nchw44.set_display(false) |
| 374 | .set_times(RUN) |
| 375 | .set_param(param) |
| 376 | .execl({{nchw44_shape, dtype::QuantizedS8(1.0)}, |
| 377 | {{}, dtype::QuantizedS8(1.0)}}); |
| 378 | auto t3 = benchmarker_float_nchw44.set_display(false) |
| 379 | .set_times(RUN) |
| 380 | .set_param(param) |
| 381 | .exec({nchw44_shape, {}}); |
| 382 | |
| 383 | printf("{%zu %zu %zu %zu} filter = %zu, stride = %zu pad = %zu\n" |
| 384 | "nchw_fp32={%.3f ms, %.3f Mflops}, " |
| 385 | "nchw44_int={%.3f ms, %.3f Mflops}, " |
| 386 | "nchw44_fp32={%.3f ms, %.3f Mflops, speed_up %f}\n\n", |
| 387 | n, c, h, w, filter, stride, pad, t1 / RUN, |
| 388 | calc_amount / (t1 / RUN * 1000), t2 / RUN, |
| 389 | calc_amount / (t2 / RUN * 1000), t3 / RUN, |
| 390 | calc_amount / (t3 / RUN * 1000), t1 / t3); |
| 391 | }; |
| 392 | // Resnet50 |
| 393 | run(1, 64, 112, 112, 3, 2, 1, param::Pooling::Mode::MAX); |
| 394 | run(1, 2048, 7, 7, 7, 1, 0, param::Pooling::Mode::AVERAGE); |
| 395 | |
| 396 | // VGG16 |
| 397 | run(1, 64, 224, 224, 2, 2, 0, param::Pooling::Mode::MAX); |
| 398 | run(1, 128, 112, 112, 2, 2, 0, param::Pooling::Mode::MAX); |
| 399 | run(1, 256, 56, 56, 2, 2, 0, param::Pooling::Mode::MAX); |
| 400 | run(1, 512, 28, 28, 2, 2, 0, param::Pooling::Mode::MAX); |
| 401 | run(1, 512, 14, 14, 2, 2, 0, param::Pooling::Mode::MAX); |
no test coverage detected