#ifndef GET_LINEAR_INPUT_HPP #define GET_LINEAR_INPUT_HPP #include #include #include #include #include #include #include #include namespace MNN { namespace LinearInput { static std::ofstream thresholdFile; static std::mutex thresholdFileMutex; static bool isFirstThreshold = true; static std::string currentThresholdFile = "thresholds.json"; static void closeThresholdFile() { std::lock_guard lock(thresholdFileMutex); if (thresholdFile.is_open()) { thresholdFile << "\n}\n"; thresholdFile.close(); MNN_PRINT("Threshold file closed: %s\n", currentThresholdFile.c_str()); } } static void initThresholdFile(const std::string& filename = "thresholds.json") { std::lock_guard lock(thresholdFileMutex); if (thresholdFile.is_open()) { thresholdFile.close(); } currentThresholdFile = filename; thresholdFile.open(filename, std::ios::out); if (thresholdFile.is_open()) { thresholdFile << "{\n"; thresholdFile.flush(); isFirstThreshold = true; MNN_PRINT("Initialized threshold file: %s\n", filename.c_str()); } else { MNN_ERROR("Failed to open threshold file: %s\n", filename.c_str()); } } static void writeThresholdRealtime(const std::string& opName, float thresholdValue) { std::lock_guard lock(thresholdFileMutex); if (!thresholdFile.is_open()) { initThresholdFile(currentThresholdFile); } if (thresholdFile.is_open()) { if (!isFirstThreshold) { thresholdFile << ",\n"; } thresholdFile << " \"" << opName << "\": " << thresholdValue; thresholdFile.flush(); isFirstThreshold = false; MNN_PRINT("Saved threshold: %s = %f\n", opName.c_str(), thresholdValue); } } static std::ofstream maxValueFile; static std::mutex maxValueFileMutex; static bool isFirstMaxValue = true; static std::string currentMaxValueFile = "max_values.json"; static void closeMaxValueFile() { std::lock_guard lock(maxValueFileMutex); if (maxValueFile.is_open()) { maxValueFile << "\n}\n"; maxValueFile.close(); MNN_PRINT("Max value file closed: %s\n", currentMaxValueFile.c_str()); } } static void initMaxValueFile(const std::string& filename = "max_values.json") { std::lock_guard lock(maxValueFileMutex); if (maxValueFile.is_open()) { maxValueFile.close(); } currentMaxValueFile = filename; maxValueFile.open(filename, std::ios::out); if (maxValueFile.is_open()) { maxValueFile << "{\n"; maxValueFile.flush(); isFirstMaxValue = true; MNN_PRINT("Initialized max value file: %s\n", filename.c_str()); } else { MNN_ERROR("Failed to open max value file: %s\n", filename.c_str()); } } static void writeMaxValueRealtime(const std::string& opName, float maxValueFloat) { std::lock_guard lock(maxValueFileMutex); if (!maxValueFile.is_open()) { initMaxValueFile(currentMaxValueFile); } if (maxValueFile.is_open()) { if (!isFirstMaxValue) { maxValueFile << ",\n"; } maxValueFile << " \"" << opName << "\": " << maxValueFloat; maxValueFile.flush(); isFirstMaxValue = false; MNN_PRINT("Saved max value: %s = %f\n", opName.c_str(), maxValueFloat); } } static void cleanupAtExit() { closeThresholdFile(); closeMaxValueFile(); } inline void initGetThreshold(const std::string& thresholdFileName, float targetSparsity) { initThresholdFile(thresholdFileName); static bool registered = false; if (!registered) { std::atexit(cleanupAtExit); registered = true; } MNN::TensorCallBackWithInfo beforeCallBack = [targetSparsity](const std::vector& ntensors, const MNN::OperatorInfo* info) { auto opName = info->name(); if (info->type() == "Copy") { return true; } if (opName.find("Linear") == std::string::npos || opName.find("raster") != std::string::npos) { return true; } for (int i = 0; i < ntensors.size(); ++i) { auto ntensor = ntensors[i]; auto outDimType = ntensor->getDimensionType(); std::shared_ptr expectTensor(new MNN::Tensor(ntensor, outDimType)); bool res = ntensor->copyToHostTensor(expectTensor.get()); if (res) { ntensor = expectTensor.get(); } { auto ninput = MNN::Express::Variable::create(MNN::Express::Expr::create(ntensor)); if (nullptr == ninput->getInfo()) { MNN_ERROR("Alloc memory or compute size error\n"); return false; } ninput = MNN::Express::_Convert(ninput, MNN::Express::NHWC); ninput = MNN::Express::_Abs(ninput); ninput = MNN::Express::_Reshape(ninput, {-1}); auto totalNum = ninput->getInfo()->dim[0]; int keepNum = totalNum * (1 - targetSparsity); auto kv = MNN::Express::_TopKV2(ninput, MNN::Express::_Scalar(keepNum)); auto values = kv[0]; auto threshold = MNN::Express::_Gather(values, MNN::Express::_Scalar(keepNum - 1)); auto thresholdValue = threshold->readMap()[0]; writeThresholdRealtime(opName, thresholdValue); } } return true; }; MNN::TensorCallBackWithInfo callBack = [](const std::vector& ntensors, const MNN::OperatorInfo* info) { return true; }; MNN::Express::ExecutorScope::Current()->setCallBack(std::move(beforeCallBack), std::move(callBack)); } inline void initGetMaxValue(const std::string& maxValueFileName) { initMaxValueFile(maxValueFileName); static bool registered = false; if (!registered) { std::atexit(cleanupAtExit); registered = true; } MNN::TensorCallBackWithInfo beforeCallBack = [](const std::vector& ntensors, const MNN::OperatorInfo* info) { auto opName = info->name(); if (info->type() == "Copy") { return true; } if (opName.find("Linear") == std::string::npos || opName.find("raster") != std::string::npos) { return true; } for (int i = 0; i < ntensors.size(); ++i) { auto ntensor = ntensors[i]; auto outDimType = ntensor->getDimensionType(); std::shared_ptr expectTensor(new MNN::Tensor(ntensor, outDimType)); bool res = ntensor->copyToHostTensor(expectTensor.get()); if (res) { ntensor = expectTensor.get(); } { auto ninput = MNN::Express::Variable::create(MNN::Express::Expr::create(ntensor)); if (nullptr == ninput->getInfo()) { MNN_ERROR("Alloc memory or compute size error\n"); return false; } ninput = MNN::Express::_Convert(ninput, MNN::Express::NHWC); ninput = MNN::Express::_Abs(ninput); ninput = MNN::Express::_Reshape(ninput, {-1}); auto kv = MNN::Express::_TopKV2(ninput, MNN::Express::_Scalar(1)); auto maxValues = kv[0]; auto maxValueFloat = maxValues->readMap()[0]; writeMaxValueRealtime(opName, maxValueFloat); } } return true; }; MNN::TensorCallBackWithInfo callBack = [](const std::vector& ntensors, const MNN::OperatorInfo* info) { return true; }; MNN::Express::ExecutorScope::Current()->setCallBack(std::move(beforeCallBack), std::move(callBack)); } inline void closeAllFiles() { closeThresholdFile(); closeMaxValueFile(); } } // namespace LinearInput } // namespace MNN #endif // GET_LINEAR_INPUT_HPP