| 28 | } |
| 29 | |
| 30 | ErrorCode CPUDynamicQuant::onExecute(const std::vector<Tensor*> &inputs, |
| 31 | const std::vector<Tensor*> &outputs) { |
| 32 | auto core = static_cast<CPUBackend*>(backend())->functions(); |
| 33 | auto int8core = static_cast<CPUBackend*>(backend())->int8Functions(); |
| 34 | float *inputPtr = inputs[0]->host<float>(); |
| 35 | int8_t *outputPtr = outputs[0]->host<int8_t>(); |
| 36 | int size = static_cast<CPUBackend*>(backend())->getTensorSize(inputs[0]); |
| 37 | float quantScale = 0.f, dequantScale = 0.f, zeroPoint = 0.f; |
| 38 | float maxVal = 0.f, minVal = 0.f; |
| 39 | core->MNNCountMaxMinValue(inputPtr, &minVal, &maxVal, size); |
| 40 | // Compute scale and zero |
| 41 | float range = maxVal - minVal; |
| 42 | MNN_ASSERT(range != 0); |
| 43 | quantScale = 255.0f / range; |
| 44 | dequantScale = range / 255.0f; |
| 45 | zeroPoint = roundf(-(minVal * 255.f) / range) - 128.0f; |
| 46 | int pack = core->pack; |
| 47 | std::vector<float> qsVec(pack, quantScale); |
| 48 | int sizeDiv = UP_DIV(size, pack); |
| 49 | int8core->MNNFloat2Int8(inputPtr, outputPtr, sizeDiv, &quantScale, -128, 127, &zeroPoint, 0); |
| 50 | float* scale = outputs[1]->host<float>(); |
| 51 | float* zeros = outputs[2]->host<float>(); |
| 52 | *scale = dequantScale; |
| 53 | *zeros = zeroPoint; |
| 54 | |
| 55 | return NO_ERROR; |
| 56 | } |
| 57 | |
| 58 | |
| 59 |
nothing calls this directly
no test coverage detected