"); //-->
https://github.com/zjhellofss/KuiperInfer 感谢大家点赞和PR, 这是对我最大的鼓励, 谢谢.
什么是表达式表达式就是一个计算过程,类似于如下:
output_mid = input1 + input2
output = output_mid * input3
用图形来表达就是这样的.
image-20230113160348886
但是在PNNX的Expession Layer中给出的是一种抽象表达式,会对计算过程进行折叠,消除中间变量. 并且将具体的输入张量替换为抽象输入@0,@1等.对于上面的计算过程,PNNX生成的抽象表达式是这样的.
add(@0,mul(@1,@2)) 抽象的表达式重新变回到一个方便后端执行的计算过程(抽象语法树来表达,在推理的时候我们会把它转成逆波兰式)。
其中add和mul表示我们上一节中说到的RuntimeOperator, @0和@1表示我们上一节课中说道的RuntimeOperand. 这个抽象表达式看起来比较简单,但是实际上情况会非常复杂,我们给出一个复杂的例子:
add(add(mul(@0,@1),mul(@2,add(add(add(@0,@2),@3),@4))),@5)
这就要求我们需要一个鲁棒的表达式解析和语法树构建功能.
我们的工作词法解析词法解析的目的就是将add(@0,mul(@1,@2))拆分为多个token,token依次为add ( @0 , mul等.代码如下:
enum class TokenType {
TokenUnknown = -1,
TokenInputNumber = 0,
TokenComma = 1,
TokenAdd = 2,
TokenMul = 3,
TokenLeftBracket = 4,
TokenRightBracket = 5,
};
struct Token {
TokenType token_type = TokenType::TokenUnknown;
int32_t start_pos = 0; //词语开始的位置
int32_t end_pos = 0; // 词语结束的位置
Token(TokenType token_type, int32_t start_pos, int32_t end_pos): token_type(token_type), start_pos(start_pos), end_pos(end_pos) {
}
};
我们在TokenType中规定了Token的类型,类型有输入、加法、乘法以及左右括号等.Token类中记录了类型以及Token在字符串的起始和结束位置.
如下的代码是具体的解析过程,我们将输入存放在statement_中,首先是判断statement_是否为空, 随后删除表达式中的所有空格和制表符.
if (!need_retoken && !this->tokens_.empty()) {
return;
}
CHECK(!statement_.empty()) << "The input statement is empty!";
statement_.erase(std::remove_if(statement_.begin(), statement_.end(), [](char c) {
return std::isspace(c);
}), statement_.end());
CHECK(!statement_.empty()) << "The input statement is empty!";
下面的代码中,我们先遍历表达式输入
for (int32_t i = 0; i < statement_.size();) {
char c = statement_.at(i);
if (c == 'a') {
CHECK(i + 1 < statement_.size() && statement_.at(i + 1) == 'd')
<< "Parse add token failed, illegal character: " << c;
CHECK(i + 2 < statement_.size() && statement_.at(i + 2) == 'd')
<< "Parse add token failed, illegal character: " << c;
Token token(TokenType::TokenAdd, i, i + 3);
tokens_.push_back(token);
std::string token_operation = std::string(statement_.begin() + i, statement_.begin() + i + 3);
token_strs_.push_back(token_operation);
i = i + 3;
}
}
char c是当前的字符,当c等于字符a的时候,我们的词法规定在token中以a作为开始的情况只有add. 所以我们判断接下来的两个字符必须是d和 d.如果不是的话就报错,如果是i的话就初始化一个新的token并进行保存.
举个简单的例子只有可能是add,没有可能是axc之类的组合.
else if (c == 'm') {
CHECK(i + 1 < statement_.size() && statement_.at(i + 1) == 'u')
<< "Parse add token failed, illegal character: " << c;
CHECK(i + 2 < statement_.size() && statement_.at(i + 2) == 'l')
<< "Parse add token failed, illegal character: " << c;
Token token(TokenType::TokenMul, i, i + 3);
tokens_.push_back(token);
std::string token_operation = std::string(statement_.begin() + i, statement_.begin() + i + 3);
token_strs_.push_back(token_operation);
i = i + 3;
}
同理当c等于字符m的时候,我们的语法规定token中以m作为开始的情况只有mul. 所以我们判断接下来的两个字必须是u和l. 如果不是的话,就报错,是的话就初始化一个mul token进行保存.
} else if (c == '@') {
CHECK(i + 1 < statement_.size() && std::isdigit(statement_.at(i + 1)))
<< "Parse number token failed, illegal character: " << c;
int32_t j = i + 1;
for (; j < statement_.size(); ++j) {
if (!std::isdigit(statement_.at(j))) {
break;
}
}
Token token(TokenType::TokenInputNumber, i, j);
CHECK(token.start_pos < token.end_pos);
tokens_.push_back(token);
std::string token_input_number = std::string(statement_.begin() + i, statement_.begin() + j);
token_strs_.push_back(token_input_number);
i = j;
} else if (c == ',') {
Token token(TokenType::TokenComma, i, i + 1);
tokens_.push_back(token);
std::string token_comma = std::string(statement_.begin() + i, statement_.begin() + i + 1);
token_strs_.push_back(token_comma);
i += 1;
}
当输入为ant时候,我们对ant之后的所有数字进行读取,如果其之后不是操作数,则报错.当字符等于(或者,的时候就直接保存为对应的token,不需要对往后的字符进行探查, 直接保存为对应类型的Token.
专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们
相关推荐
CSR8670CSR8675智能语音Alexa蓝牙方案开发
EEPW2018年3月刊(工业物联网)
WTC-AI太阳能热水器电路图
瑞萨电子AI单元解决方案成功提高GE医疗(日本)日野工厂的生产力
基于Microchip MCU的AI/ML培训教程1
EEPW2018年6月刊(5G)
基于Ai-WB2-12F与Rd-04的雷达检测系统
万家乐JSYZ5-AI燃气热水器电路图
AI竞争进入下半场:从“卷参数”到“卷单价”
继上次海联达Ai-ap100拆机之电源改造
尼吉康的事业介绍
研华 COMPUTEX 首度整合全球伙伴大会 强化全球边缘 AI 生态系统联结
GPU:面临工作负载转变的高吞吐架构
AI热潮引发多层陶瓷电容MLCC供应短缺
电子元件培训教材
基于VisitionX制造智能眼镜
海联达(Aigale)Ai-HD1 无线全高清套件拆解
释说芯语16:硬科技:构建企业未来之路(附PPT)
紧凑型集成连接器模块抑制噪声 为人工智能应用实现以太网供电
英伟达CFO:我们早就知道内存大涨价要来了
AI 驱动估值飙升:光通信半导体企业市值暴涨
WTC-AI型太阳能热水器电路图
PowiGaN for AI Data Centers: Unmatched Power Density and Reliability
赋能边缘端对话式人工智能
人工智能是如何帮助阻止造假者的?
iCAN-4017 AI功能模块
爱立信携手 Net Feasa 布局海事网络 融合公网级通信与智能体 AI 赋能航运
Nigel AI赋能LabVIEW,NI用AI重塑测试新边界
基于Microchip MCU的AI/ML培训教程3
基于Microchip MCU的AI/ML培训教程2