当前位置: 首页 > news >正文

土豆做视频在线观看网站网站设计费 建设费入什么科目

土豆做视频在线观看网站,网站设计费 建设费入什么科目,wordpress 女性模板,高端网站建设kgwl一、 Arm架构寄存器体系熟悉 基于arm neon 实现的代码有 intrinsic 和inline assembly 两种实现。 1.1 通用寄存器 arm v7 有 16 个 32-bit 通用寄存器#xff0c;用 r0-r15 表示。 arm v8 有 31 个 64-bit 通用寄存器#xff0c;用 x0-x30 表示#xff0c;和 v7 不一样…一、 Arm架构寄存器体系熟悉 基于arm neon 实现的代码有 intrinsic 和inline assembly 两种实现。 1.1 通用寄存器 arm v7 有 16 个 32-bit 通用寄存器用 r0-r15 表示。 arm v8 有 31 个 64-bit 通用寄存器用 x0-x30 表示和 v7 不一样的是这 31 个寄存器也可以作为 32-bit 寄存器来用用 w0-w30 表示其中 wn 是 xn 的低 32 位如下图所示 函数前四个参数会按顺序被放入寄存器 r0-r3w0-w3 剩下会采用压栈的方式保存 寄存器寄存器别名用途r0a1第一个函数参数: Scratch 寄存器r1a2第二个函数参数: Scratch 寄存器r2a3第三个函数参数: Scratch 寄存器r3a4第四个函数参数: Scratch 寄存器r4v1寄存器变量r5v2寄存器变量r6v3寄存器变量r7v4寄存器变量r8v5寄存器变量r9v6 rfp寄存器变量 实际的帧指针r10sl栈接线r11fp参数指针r12ip临时r13sp栈指针r14lr连接寄存器r15pc程序计数 1.2 向量寄存器 armv7 包含 16 个 128-bit 向量寄存器用 q0-q15 表示其中每个 q 寄存器又可以拆分成两个 64-bit 向量寄存器来用用 d0-d31 来表示。 armv8 则有更多的向量寄存器32 个 128-bit 向量寄存器用 v0-v31 来表示。 每个 128-bit 向量寄存器可以当做 包含 2 个 64-bit 元素的向量寄存器来用表达形式是 vn.2d 包含 4 个 32-bit 元素的向量寄存器来用表达形式是 vn.4s 包含 8 个 16-bit 元素的向量寄存器来用表达形式是 vn.8h 包含 16 个 8-bit 元素的向量寄存器来用表达形式是 vn.16b 或者每个向量寄存器也可以只用低 64-bit 1 个 64-bit 元素的向量寄存器来用表达形式是 vn.1d 2 个 32-bit 元素的向量寄存器来用表达形式是 vn.2s 4 个 16-bit 元素的向量寄存器来用表达形式是 vn.4h 8 个 8-bit 元素的向量寄存器来用表达形式是 vn.8b 利用指令集加速无一例外地要利用专用寄存器这种在 CPU 上稀少、宝贵的资源。专用寄存器用少了 CPU 的性能不能充分发挥用多了则会产生寄存器溢出 (Register Spilling(https://blog.csdn.net/qq_41112170/article/details/90286091) 这种对性能有明显负面影响的问题。因此我们至少需要了解在编写 Neon 代码时有多少个专用寄存器可供利用。 二、内联汇编 2.1 基础写法 __asm__ qualifiers ( // 汇编代码部分 : OutputOperands //在内联汇编代码中被修改的变量列表 : InputOperands //在内联汇编代码中用到的变量列表 : Clobbers //在内联汇编代码中用到的寄存器列表 ); qualifiers一般是用 volatile 修饰词 关键字__volatile__也可以写“volatile”理由同上__volatile__是可选的作用是禁止编译器对后面汇编指令再进行优化。一般自己写的汇编考虑性能已经做过优化编译器再优化的话可能效果反而更差所以通常还是带上这个关键字 括号里是真正的汇编代码主要有四部分组成第一部分是具体的汇编代码是必须的其他三个为辅助参数可选各部分之间用冒号“:”分割即使参数为空也要加冒号 OutputOperands在内联汇编中会被修改的变量列表变量之间用,隔开 每个变量的格式是 [asmSymbolicName] constraint(cvariablename) cvariablename表示变量原来的名字 asmSymbolicName表示变量在内联汇编代码中的别名一般和 cvariablename 一样在汇编代码中就可以通过%[asmSymbolicName]去使用该变量 constraint: 一般填r具体解释见文档[6] InputOperands在内联汇编中用到的所有变量列表变量之间用,隔开 每个变量的格式是 [asmSymbolicName] constraint(cexpression) 和输出不一样地方是首先要按OutputOperands列表的顺序再列一遍但是constraint用数字代替从0开始然后才是写其他只读变量只读变量constraint填r。 Clobbers: 一般是cc, memory开头然后接着填内联汇编中用到的通用寄存器和向量寄存器 cc表示内联汇编代码修改了标志寄存器 memory表示汇编代码对输入和输出操作数执行内存读取或写入操作读写参数列表之一的变量指向的内存 输入列表 (r (some_input)): 这表明 some_input 是一个输入操作数它的值在汇编执行前被读取。r 约束表示 some_input 被存储在某个寄存器中具体哪个寄存器由编译器决定。 输出列表 (r (result)): 这表明 result 是一个输出操作数它的值在汇编执行后被写回。 约束表示 result 既可以作为输入也可以作为输出汇编代码可以读取它的初始值并在执行过程中更新它的值。 约束说明 r将值放入任意一个可用的寄存器中。 r将值放入任意一个可用的寄存器中并且该寄存器在操作后还会被写回即它既可以作为输入也可以作为输出。 w类似于 r但表示该值在汇编代码中可能会被修改并且修改后的值需要写回原始变量。 m表示该值应该被加载到内存地址中通常与指针一起使用。 asm(mov %0,%1:r(val1):r(val2):); 由上面对指令语法的描述进行分析 输出操作数为 val1属性为 r。 输入操作数为 val2属性为 r code 部分为 mov %1,%0, %0 表示输入输出列表中的第一个操作数 %1 表示操作数列表中提供的第二个操作数以此类推这条汇编指令很明显就是将第二个操作数(val2)赋值给第一个操作数(val1),所以最后的结果为 val1 222. 。 int x10, y; __asm__ (mov %[in],%[out]: [out]r(y): [in]r(x): );如果指定了别名的话那在汇编模板中引用该变量就可以使用别名增加可读性 2.2 操作符含义 表示只写通常用于所有输出操作数的属性 表示读写只能被列为输出操作数的属性否则编译会报错。 只能用作输出 限定符 ARM指令集含义 r 通用寄存器 f 浮点寄存器 m 内存地址 为保持寄存器内存数据一致性提供三个类型 类型作用r0…r15告诉编译器汇编代码中修改了寄存器r0…r15 (v8 是x, v)cc告诉编译器汇编代码会导致CPU状态位的改变memory告诉编译器汇编代码会读取或修改内存中某个地址存放的值 三、样例分析 对于刚入门优化的同学改写汇编最好先从 C 改写 intrinsic 开始然后再根据 intrinsic 的代码去改写汇编一般 intrinsic 的指令和汇编指令都能对应的上当然高手可以直接跳过去写汇编但是对于新手建议还是一步步来。 而且比较重要的一点是我认为 算法上的改进更为重要假设你 C 算法层面代码已经定下来了对于性能还想有更进一步的提升那么可以尝试去写 neon 汇编内联或者纯汇编但不是说汇编是万能的这个和你的优化经验还有算法本身的复杂度有很大关系可能你吭哧坑次改完发现还做了负优化因为编译器本身也会做向量化。 3.1 两个数组加权和 第一个例子是两个数组对应元素加权和例子足够简单方便讲解改写汇编的一些思路。 下面代码为了可读性会相应的作简. 3.1.1 c 实现 bool arrWeightedAvg(const float *arr1,const float arr1Weight,const float *arr2,const float arr2Weight,const int len,float *resultArr) {for (int i 0; i len; i) {resultArr[i] arr1[i] * arr1Weight arr2[i] * arr2Weight;}return true; } 3.1.2 改 intrinsic 对于 intrinsic 代码是兼容 armv7 和 v8 的所以不同架构之间迁移也方便不需要改代码 bool arrWeightedAvgIntrinsic(const float *arr1,const float arr1Weight,const float *arr2,const float arr2Weight,const int len,float *resultArr) {int neonLen len 2;int remain len - (neonLen 2);// 这里向量化主要思路是循环内每次// 处理4个元素的加权和// 所以neonLen是数组长度len除4// 而剩下的尾部元素按正常处理float *resultArrPtr resultArr;const float *arr1Ptr arr1;const float *arr2Ptr arr2;// 因为一次处理4个元素// 所以权值要拷贝4份放到// 一个float32x4_t类型变量中// 也相当于是128-bit向量寄存器float32x4_t arr1Wf4 vdupq_n_f32(arr1Weight);float32x4_t arr2Wf4 vdupq_n_f32(arr2Weight);for (int i 0; i neonLen; i) {// 分别读4个数组元素float32x4_t arr1f4 vld1q_f32(arr1Ptr);float32x4_t arr2f4 vld1q_f32(arr2Ptr);// eltwise乘法arr1f4 vmulq_f32(arr1f4, arr1Wf4);arr2f4 vmulq_f32(arr2f4, arr2Wf4);// eltwise加法float32x4_t resultf4 vaddq_f32(arr1f4, arr2f4);// 写结果vst1q_f32(resultArrPtr, resultf4);arr1Ptr 4;arr2Ptr 4;resultArrPtr 4;}// 处理尾部元素for (; remain 0; remain --) {*resultArrPtr (*arr1Ptr) * arr1Weight (*arr2Ptr) * arr2Weight;resultArrPtr ;arr1Ptr ;arr2Ptr ;}return true; } 3.1.3 arm v7 内联汇编 bool arrWeightedAvgIntrinsic(const float *arr1,const float arr1Weight,const float *arr2,const float arr2Weight,const int len,float *resultArr) {int neonLen len 2;int remain len - (neonLen 2);// 这里向量化主要思路是循环内每次// 处理4个元素的加权和// 所以neonLen是数组长度len除4// 而剩下的尾部元素按正常处理float *resultArrPtr resultArr;const float *arr1Ptr arr1;const float *arr2Ptr arr2;// 因为一次处理4个元素// 所以权值要拷贝4份放到// 一个float32x4_t类型变量中// 也相当于是128-bit向量寄存器float32x4_t arr1Wf4 vdupq_n_f32(arr1Weight);float32x4_t arr2Wf4 vdupq_n_f32(arr2Weight);for (int i 0; i neonLen; i) {// 分别读4个数组元素float32x4_t arr1f4 vld1q_f32(arr1Ptr);float32x4_t arr2f4 vld1q_f32(arr2Ptr);// eltwise乘法arr1f4 vmulq_f32(arr1f4, arr1Wf4);arr2f4 vmulq_f32(arr2f4, arr2Wf4);// eltwise加法float32x4_t resultf4 vaddq_f32(arr1f4, arr2f4);// 写结果vst1q_f32(resultArrPtr, resultf4);arr1Ptr 4;arr2Ptr 4;resultArrPtr 4;}// 处理尾部元素for (; remain 0; remain --) {*resultArrPtr (*arr1Ptr) * arr1Weight (*arr2Ptr) * arr2Weight;resultArrPtr ;arr1Ptr ;arr2Ptr ;}return true; } 3.1.4 armv8 内联汇编 #ifdef __aarch64__ // armv8__asm__ volatile(mov x0, %[arr1Weight] \n // 将weight1的值移动到通用寄存器x0中。dup v0.4s, w0 \n //w0是x0的低32位 复制值到向量寄存器v0中当成4*32来使用。mov x1, %[arr2Weight] \ndup v1.4s, w1 \n0: \n //循环结束条件小于0.prfm pldl1keep, [%[arr1Ptr], #128] \n //预读取arr1地址开始的128bit 数据就是4个32bit的数据。ld1 {v2.4s}, [%[arr1Ptr]], #16 \n // 将数据加载到v2 向量寄存器中 并且地址自增16个字节。prfm pldl1keep, [%[arr2Ptr], #128] \nld1 {v3.4s}, [%[arr2Ptr]], #16 \nfmul v4.4s, v2.4s, v0.4s \n //数组1和权重相乘。保存在v4 寄存器中。fmul v5.4s, v3.4s, v1.4s \n // 数据2和权重相乘保存在v5 寄存器中。fadd v6.4s, v4.4s, v5.4s \n //将寄存器v4, v5的值相加 保存在v6寄存器中。subs %[neonLen], %[neonLen], #1 \n // 对应 neonLen-- sub指令后面加个s表示会更新条件flagst1 {v6.4s}, [%[resultArrPtr]], #16 \n //将寄存器v6的结果写入到目的地址resultarrptr, 地址自增16字节。4个数一个数四字节bgt 0b \n //b跳转指令 gt 判断是不是大于0条件判断 大于0 跳转到0的位置。:[arr1Ptr] r(arr1Ptr),[arr2Ptr] r(arr2Ptr),[resultArrPtr] r(resultArrPtr),[neonLen] r(neonLen):[arr1Weight] r(arr1Weight),[arr2Weight] r(arr2Weight):cc, memory, x0, x1, v0, v1, v2, v3, v4, v5, v6, v7); 反编译系统的编译文件进行汇编代码对比学习。 ./llvm-objdump -d /home/lsq/wind/wind_develop_my/wind/build_android/src/backend/cpu/CMakeFiles/Wi ndCPU.dir/kernel/neon/matmul_quant_test.cc.o 内联汇编的目的是进行汇编指令的优化尽可能的直接操作寄存器利用新特性进行代码的加速。更多的指令需要查找官方文档进行学习。 3.2 汇编指令对应的机器码生成 .inst 0x4e80a4d8 是一个汇编指令用于在 ARM 架构中直接插入机器码。这个指令的格式是 .inst 机器码其中 机器码 是一个 32 位或 64 位的十六进制值表示一条机器指令。 具体来说0x4e80a4d8 是一个 32 位的机器码。为了理解这个机器码是如何编码的我们需要查看 ARMv8 指令集的文档特别是 NEON 指令集的文档。 3.2.1 使用 LLVM 工具 可以安装 llvm 工具链然后运行如下命令、 echo smmla v16.4s, v4.16b, v0.16b | llvm-mc -archaarch64 -mattrneon,i8mm -show-encoding 这将会输出汇编指令对应的机器码。如果没有安装 llvm-mc 工具可以参考以下汇编器指令来生成机器码。 3.2.2 使用 GNU 汇编器 你可以使用 arm-none-eabi-as 工具来编译汇编代码并生成机器码。下面是一个示例 echo .arch armv8-a; smmla v16.4s, v4.16b, v0.16b | arm-none-eabi-as -o - -a - 3.2.3 在线工具 https://armconverter.com/ 3.2.4 反编译编译产物 ./llvm-objdump -d /home/lsq/wind/wind_develop_my/wind/build_android/src/backend/cpu/CMakeFiles/WindCPU.dir/kernel/neon/matmul_quant_test.cc.o 反汇编结果 .inst 0x4e80a490 \n // smmla v16.4s, v4.16b, v0.16b //v0_01s// *y0_0.inst 0x4e81a4b5 \n // smmla v21.4s, v5.16b, v1.16b //v0_0hs// *y0_1.inst 0x4e82a4da \n // smmla v26.4s, v6.16b, v2.16b //v0_1ls// *y0_2.inst 0x4e83a4ff \n // smmla v31.4s, v7.16b, v3.16b// v0_1hs 四、附录 https://medium.com/warmap_/%E8%BD%AC-%E5%A6%82%E4%BD%95%E5%9C%A8c%E6%88%96c-%E4%BB%A3%E7%A0%81%E4%B8%AD%E5%B5%8C%E5%85%A5arm%E6%B1%87%E7%BC%96%E4%BB%A3%E7%A0%81-a3704e164de8 http://giantpandacv.com/project/%E9%83%A8%E7%BD%B2%E4%BC%98%E5%8C%96/AI%20%E7%A7%BB%E5%8A%A8%E7%AB%AF%E7%AE%97%E6%B3%95%E4%BC%98%E5%8C%96/%E7%A7%BB%E5%8A%A8%E7%AB%AFarm%20cpu%E4%BC%98%E5%8C%96%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/%E7%A7%BB%E5%8A%A8%E7%AB%AFarm%20cpu%E4%BC%98%E5%8C%96%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%E7%AC%AC4%E5%BC%B9--%E5%86%85%E8%81%94%E6%B1%87%E7%BC%96%E5%85%A5%E9%97%A8/
http://www.dnsts.com.cn/news/62300.html

相关文章:

  • 做网站 搞流量 赚广告费怎样进入医院公众号
  • 徐州建设网站价格桂林两江四湖图片
  • wap免费空间成都爱站网seo站长查询工具
  • 在一个城市做相亲网站企业邮箱费用
  • 优惠券网站cms建设公司网站建设需要哪些方面
  • 团购网站开发语言wordpress move导入数据
  • 盛唐网站建设金华网站建设策划
  • 深圳专业网站建设丝芙兰网站做的好差
  • 网站项目需求表大连中山网站建设
  • discuz修改网站标题网络运营商有哪些
  • 留言板网站模板哪家公司做网站便宜
  • 怎么做淘宝网站建网站 必须学html吗
  • 调查问卷在哪个网站做wordpress多站点 seo
  • 公司门户网站模板网站建设中服务器的搭建方式有几种
  • 演出公司网站建设网站收录申请
  • 雄县网站制作建设中心网站文章优化技巧
  • 做期货在哪个网站查资料室内设计网站
  • 建站平台塔山双喜可以做笔试面试题的网站
  • 好便宜建站机房建设网站模板
  • 深圳网站建设优化czzhwmo2o网站建设特色
  • 化妆品网站的建设方案网站开发前端学习
  • 商丘集团网站建设淮北论坛网官网
  • 专门做餐饮ppt的网站上海发布公众号下载安装
  • 医院网站建设方案招标文件网站规划和建设方案
  • 房产网贷平台seo撰写网站标题以及描述的案例
  • 涂料网站源码百度推广怎么收费
  • 网站查询系统怎么做免费企业网站源码大全
  • 网站改版思路wordpress 插件如何使用
  • 做网站的时候用的什么框架合肥网站建设方案
  • 十大电子商务网站html怎么做商品页面