| 498 | } |
| 499 | |
| 500 | static std::unique_ptr<IDSTQuanT> encode(const float* weight, const std::vector<float>& scale, int kernelSize, |
| 501 | int kernelNum, bool asymmetricQuantFlag, const int8_t* quantWeightPtr, |
| 502 | const int clampMin, const EncodeOptions& opts = {}) { |
| 503 | const int bits = opts.bits; |
| 504 | const bool detectSparse = opts.detectSparse; |
| 505 | const bool scaleFp16 = (opts.scaleBit == 16); |
| 506 | // compute block_size |
| 507 | auto alpha_size = scale.size(); |
| 508 | auto block_size = kernelSize; |
| 509 | auto block_num = 1; |
| 510 | if (asymmetricQuantFlag) { |
| 511 | alpha_size /= 2; |
| 512 | } |
| 513 | if (alpha_size > kernelNum) { |
| 514 | block_num = alpha_size / kernelNum; |
| 515 | block_size = kernelSize / block_num; |
| 516 | } |
| 517 | bool shapeUseInt32 = false; |
| 518 | std::unique_ptr<IDSTQuanT> idst(new IDSTQuanT); |
| 519 | std::ostringstream outputStringStreamCQ; |
| 520 | idst->aMaxOrBits = bits; |
| 521 | if (quantWeightPtr && nullptr == weight) { |
| 522 | WriteCQBlobsInt8(outputStringStreamCQ, quantWeightPtr, kernelSize, kernelNum, shapeUseInt32, bits); |
| 523 | auto cqStr = outputStringStreamCQ.str(); |
| 524 | idst->type = 1; |
| 525 | idst->buffer.resize(cqStr.size()); |
| 526 | ::memcpy(idst->buffer.data(), cqStr.data(), cqStr.size()); |
| 527 | } else { |
| 528 | WriteCQBlobs(outputStringStreamCQ, weight, scale.data(), kernelSize, kernelNum, asymmetricQuantFlag, shapeUseInt32, bits); |
| 529 | auto cqStr = outputStringStreamCQ.str(); |
| 530 | if (detectSparse) { |
| 531 | std::ostringstream outputStringStreamSQ; |
| 532 | bool sparseValid = WriteSparseQuanBlobs(outputStringStreamSQ, weight, scale.data(), kernelSize, kernelNum, asymmetricQuantFlag, shapeUseInt32, bits); |
| 533 | auto sqStr = outputStringStreamSQ.str(); |
| 534 | int int8Size = kernelNum * kernelSize; |
| 535 | if (cqStr.size() <= sqStr.size() || (!sparseValid)) { |
| 536 | idst->type = 1; |
| 537 | idst->buffer.resize(cqStr.size()); |
| 538 | ::memcpy(idst->buffer.data(), cqStr.data(), cqStr.size()); |
| 539 | } else { |
| 540 | idst->type = 2; |
| 541 | idst->buffer.resize(sqStr.size()); |
| 542 | ::memcpy(idst->buffer.data(), sqStr.data(), sqStr.size()); |
| 543 | } |
| 544 | } else { |
| 545 | idst->type = 1; |
| 546 | idst->buffer.resize(cqStr.size()); |
| 547 | ::memcpy(idst->buffer.data(), cqStr.data(), cqStr.size()); |
| 548 | } |
| 549 | } |
| 550 | idst->shapeInt32 = shapeUseInt32; |
| 551 | if (scaleFp16) { |
| 552 | idst->scaleStorage = ScaleStorageType_FP16; |
| 553 | idst->alphaFp16.resize(scale.size()); |
| 554 | for (size_t i = 0; i < scale.size(); ++i) { |
| 555 | half_float::half h(scale[i]); |
| 556 | std::memcpy(&idst->alphaFp16[i], &h, sizeof(uint16_t)); |
| 557 | } |