| 555 | } |
| 556 | |
| 557 | Status ClGemmLowpMatrixMultiplyCore::validate(const ITensorInfo *a, |
| 558 | const ITensorInfo *b, |
| 559 | const ITensorInfo *c, |
| 560 | const ITensorInfo *output, |
| 561 | const GEMMInfo &gemm_info) |
| 562 | { |
| 563 | ARM_COMPUTE_ERROR_ON_NULLPTR(a, b, output); |
| 564 | ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(a, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED); |
| 565 | ARM_COMPUTE_RETURN_ERROR_ON_DATA_TYPE_CHANNEL_NOT_IN(b, 1, DataType::QASYMM8, DataType::QASYMM8_SIGNED, |
| 566 | DataType::QSYMM8, DataType::QSYMM8_PER_CHANNEL); |
| 567 | ARM_COMPUTE_RETURN_ERROR_ON(a->data_type() == DataType::QASYMM8 && b->data_type() == DataType::QASYMM8_SIGNED); |
| 568 | ARM_COMPUTE_RETURN_ERROR_ON(a->data_type() == DataType::QASYMM8_SIGNED && b->data_type() == DataType::QASYMM8); |
| 569 | ARM_COMPUTE_RETURN_ERROR_ON_MSG(gemm_info.is_a_reshaped(), "Matrix A already reshaped is not supported"); |
| 570 | ARM_COMPUTE_RETURN_ERROR_ON_MSG(gemm_info.is_b_reshaped(), "Matrix B already reshaped is not supported"); |
| 571 | |
| 572 | int32_t a_offset = a->quantization_info().uniform().offset; |
| 573 | int32_t b_offset = b->quantization_info().uniform().offset; |
| 574 | |
| 575 | const ITensorInfo *matrix_a_info = a; |
| 576 | |
| 577 | TensorInfo tmp_b_info{}; |
| 578 | GEMMRHSMatrixInfo rhs_info; |
| 579 | GEMMLHSMatrixInfo lhs_info; |
| 580 | |
| 581 | // Get the GPU target |
| 582 | const GPUTarget gpu_target = CLScheduler::get().target(); |
| 583 | |
| 584 | bool reinterpret_input_as_3d = gemm_info.reinterpret_input_as_3d(); |
| 585 | const unsigned int m = reinterpret_input_as_3d ? (a->dimension(1) * a->dimension(2)) : a->dimension(1); |
| 586 | const unsigned int n = b->dimension(0); |
| 587 | const unsigned int k = a->dimension(0); |
| 588 | const unsigned int batch_size = reinterpret_input_as_3d ? a->dimension(3) : a->dimension(2); |
| 589 | const int depth_output_gemm3d = gemm_info.depth_output_gemm3d(); |
| 590 | |
| 591 | bool reshape_matrix_b = is_gemm_reshaped( |
| 592 | auto_select_gemm_kernel(auto_heuristics::CommonQuery{gpu_target, a->data_type(), m, n, k, batch_size}, |
| 593 | gemm_info.reshape_b_only_on_first_run())); |
| 594 | |
| 595 | const GEMMReshapeInfo reshape_info = GEMMReshapeInfo(m, n, k, 1, 1, depth_output_gemm3d, reinterpret_input_as_3d); |
| 596 | |
| 597 | bool convert_to_qasymm8 = is_data_type_quantized_per_channel(b->data_type()) && |
| 598 | is_data_type_quantized_symmetric(b->data_type()) && |
| 599 | is_data_type_quantized_asymmetric(a->data_type()); |
| 600 | TensorInfo weights_info(*b); |
| 601 | if (convert_to_qasymm8) |
| 602 | { |
| 603 | b_offset = -128; |
| 604 | weights_info.set_data_type(DataType::QASYMM8); |
| 605 | ARM_COMPUTE_RETURN_ON_ERROR(ClCastKernel::validate(b, &weights_info, ConvertPolicy::WRAP)); |
| 606 | } |
| 607 | const ITensorInfo *matrix_b_info = &weights_info; |
| 608 | if (reshape_matrix_b) |
| 609 | { |
| 610 | matrix_b_info = &tmp_b_info; |
| 611 | |
| 612 | // Pick up the GEMM configuration |
| 613 | // NOTE: No need to validate mlgo configurations as they automatically fall back to default heuristics if validation fails |
| 614 | // It doesn't matter whether Datatype is DataType::QASYMM8 or DataType::QASYMM8_SIGNED, since it only affect the shape configuration |
nothing calls this directly
no test coverage detected