.Net7矢量化的性能优化
矢量化是性能优化的重要技术,也是寄托硬件层面的优化技术。本篇来看下。
(资料图片)
一:矢量化支持的问题:矢量化的System.Runtime.Intrinsics.X86.Sse2.MoveMask函数和矢量化的Vector128.Create().ExtractMostSignificantBits()函数返回的结果是一样的。但是前者只能在支持SSE2的128位矢量化平台上工作,而后者可以在任何支持128位矢量化平台上工作,包括Risc-V,Arm64,WASM等平台。这里以一段代码看下:
private static void Main(){ Vector128 v = Vector128.Create((byte)123); while (true) { WithIntrinsics(v); WithVector(v); break; }}[MethodImpl(MethodImplOptions.NoInlining)]private static int WithIntrinsics(Vector128 v) => Sse2.MoveMask(v);[MethodImpl(MethodImplOptions.NoInlining)]private static uint WithVector(Vector128 v) => v.ExtractMostSignificantBits(); 看下它的ASM代码:
WithIntrinsics:G_M000_IG01: ;; offset=0000H 55 push rbp C5F877 vzeroupper 488BEC mov rbp, rsp 48894D10 mov bword ptr [rbp+10H], rcxG_M000_IG02: ;; offset=000BH 488B4510 mov rax, bword ptr [rbp+10H] C5F91000 vmovupd xmm0, xmmword ptr [rax] C5F9D7C0 vpmovmskb eax, xmm0G_M000_IG03: ;; offset=0017H 5D pop rbp C3 retWithVectorG_M000_IG01: ;; offset=0000H 55 push rbp C5F877 vzeroupper 488BEC mov rbp, rsp 48894D10 mov bword ptr [rbp+10H], rcxG_M000_IG02: ;; offset=000BH 488B4510 mov rax, bword ptr [rbp+10H] C5F91000 vmovupd xmm0, xmmword ptr [rax] C5F9D7C0 vpmovmskb eax, xmm0G_M000_IG03: ;; offset=0017H 5D pop rbp C3 ret可以看到这两个函数生成的ASM几乎一模一样。
2.矢量化的一个例子由于以上代码体现的SSE2的局限性,所以需要把一些代码矢量化,以便在任何平台上运行,这里看一个例子。
static bool Contains(ReadOnlySpan haystack, byte needle){ for (int i = 0; i < haystack.Length; i++) { if (haystack[i] == needle) { return true; } } return false;} 查找元素,找到了然后返回。怎么对这例子进行矢量化呢?首先需要判断你代码运行的硬件是否支持矢量化,可以通过Vector.IsHardwareAccelerated的返回值来判断。其次,传入的变量长度(haystack.length)必须的大于一个向量的长度(Vector
static bool Contains(ReadOnlySpan haystack, byte needle){ if (Vector.IsHardwareAccelerated && haystack.Length >= Vector.Count) { // ... } else { for (int i = 0; i < haystack.Length; i++) { if (haystack[i] == needle) { return true; } } } return false;} 如果以上if的两个判断均为true的话,那么我们进入矢量化阶段。代码如下:
static unsafe bool Contains(ReadOnlySpan haystack, byte needle){ if (Vector.IsHardwareAccelerated && haystack.Length >= Vector.Count)//判断当前运行的硬件是否符合矢量化以及变量的长度不能小于矢量化里面一个向量的长度。 { fixed (byte* haystackPtr = &MemoryMarshal.GetReference(haystack))//获取变量的头指针 { Vector target = new Vector(needle);//向量化需要查找的变量needle byte* current = haystackPtr;//变量haystack的头指针,以便于后面循环 byte* endMinusOneVector = haystackPtr + haystack.Length - Vector.Count;//头指针+变量的长度减去一个向量的长度。同头指针current开始到endMinusOneVector在这个里面遍历循环,查找需要查找的变量target也就是向量化的needle,这里为什么要进去Vector.Count因为向量是从0开始查找的。 do { if (Vector.EqualsAny(target, *(Vector*)current))//判断当前的指针是否与需要查找的变量相等 { return true;//相等就返回true } current += Vector.Count;//不相等指针就位移到下一个向量,继续遍历循环。 } while (current < endMinusOneVector);//这里判断是否达到循环终点。 } } else { for (int i = 0; i < haystack.Length; i++) { if (haystack[i] == needle) { return true; } } } return false;} 以上代码几乎完成了90%,但是依然有点点问题。那就是最后一个向量endMinusOneVector没有被查找。所以还需要加上它的查找。最后的点如下,第一个Contains是不矢量化的,第二个Contains_Vector是矢量化之后的。
static bool Contains(ReadOnlySpan haystack, byte needle){ for (int i = 0; i < haystack.Length; i++) { if (haystack[i] == needle) { return true; } } return false;}static unsafe bool Contains_Vector(ReadOnlySpan haystack, byte needle){ if (Vector.IsHardwareAccelerated && haystack.Length >= Vector.Count) { fixed (byte* haystackPtr = &MemoryMarshal.GetReference(haystack)) { Vector target = new Vector(needle); byte* current = haystackPtr; byte* endMinusOneVector = haystackPtr + haystack.Length - Vector.Count; do { if (Vector.EqualsAny(target, *(Vector*)current)) { return true; } current += Vector.Count; } while (current < endMinusOneVector); if (Vector.EqualsAny(target, *(Vector*)endMinusOneVector)) { return true; } } } else { for (int i = 0; i < haystack.Length; i++) { if (haystack[i] == needle) { return true; } } } return false;} 上面的代码几乎是完美的,测试下基准
private byte[] _data = Enumerable.Repeat((byte)123, 999).Append((byte)42).ToArray();//Enumerable.Repeat表示999个123的byte,放在数组,最后又加了一个42数值到数组[Benchmark(Baseline = true)][Arguments((byte)42)]public bool Find(byte value) => Contains(_data, value); // just the fallback path in its own method[Benchmark][Arguments((byte)42)]public bool FindVectorized(byte value) => Contains_Vectorized(_data, value); // the implementation we just wrote| Method | value | Mean | Error | StdDev | Ratio | Code Size ||--------------- |------ |----------:|---------:|---------:|------:|----------:|| Find | 42 | 508.42 ns | 2.336 ns | 2.185 ns | 1.00 | 110 B || FindVectorized | 42 | 21.57 ns | 0.342 ns | 0.303 ns | 0.04 | 253 B |可以看到矢量化之后的性能,进行了夸张的25倍的增长。这段代码几乎完美,但是并不完美。这里是用的1000个元素测试,如果是小于30个元素呢?有两个方法,第一个是退回到没有矢量化的代码也就是Contains函数,第二个是把Vector切换到128位来操作。代码如下,几乎没变更:
static unsafe bool Contains128(ReadOnlySpan haystack, byte needle){ if (Vector128.IsHardwareAccelerated && haystack.Length >= Vector128.Count) { ref byte current = ref MemoryMarshal.GetReference(haystack); Vector128 target = Vector128.Create(needle); ref byte endMinusOneVector = ref Unsafe.Add(ref current, haystack.Length - Vector128.Count); do { if (Vector128.EqualsAny(target, Vector128.LoadUnsafe(ref current))) { return true; } current = ref Unsafe.Add(ref current, Vector128.Count); } while (Unsafe.IsAddressLessThan(ref current, ref endMinusOneVector)); if (Vector128.EqualsAny(target, Vector128.LoadUnsafe(ref endMinusOneVector))) { return true; } } else { for (int i = 0; i < haystack.Length; i++) { if (haystack[i] == needle) { return true; } } } return false;} 来进行一个基准测试:
private byte[] _data = Enumerable.Repeat((byte)123, 29).Append((byte)42).ToArray();[Benchmark(Baseline = true)][Arguments((byte)42)]public bool Find(byte value) => Contains(_data, value);[Benchmark][Arguments((byte)42)]public bool FindVectorized(byte value) => Contains_Vectorized(_data, value);| Method | value | Mean | Error | StdDev | Ratio | Code Size ||--------------- |------ |----------:|----------:|----------:|------:|----------:|| Find | 42 | 16.363 ns | 0.1833 ns | 0.1530 ns | 1.00 | 110 B || FindVectorized | 42 | 1.799 ns | 0.0320 ns | 0.0299 ns | 0.11 | 191 B |同样的性能进行了16倍的提速。
结尾作者:江湖评谈欢迎关注公众号:jianghupt。文章首发。
标签:
- .Net7矢量化的性能优化
- 速读:有声翻译英语发音朗读_有声翻译
- 上海城市更新报告·愚园路丨网红街区的生意经
- 魔兽世界踏梦者 魔兽世界英雄榜
- 京沪高铁:公司未参与京沪二通道的投资建设-全球讯息
- 世界聚焦:总销售额破1.4亿元 东方甄选四川行圆满收官
- 把放错位的资源分好类
- 【全球新要闻】今日成立专项助学基金,江歌妈妈将69.6万赔偿款全额捐出
- 利好刺激 智能汽车主题ETF领涨 天天观焦点
- 勇闯十层大山的军人
- 日本北海道地区发生6.2级地震
- 天天热文:未按施工技术标准质量控制,深圳市正大建业建筑工程有限公司被罚
- “碳”路指数投资!新华碳科技指数在沪正式发布-天天实时
- 002118-002118会不会退市
- 每日短讯:丢失sldinnerdispatchproxyu.dll的修复方法
- amazed用法(amazed)_新资讯
- 每日消息!世纪公园烟花节时间表_世纪公园烟花节
- 阿里P9下岗再就业
- 今日最新!唤醒身体并击退负面情绪 《跑步穿过阴云密布》收录35个真实故事
- 视讯!【夏收现场】 知识落“地”助丰收 耕地质量提升示范田小麦增产53.6%
- 刘亚仁涉嫌使用毒品种类追加, 新发现2种一共七种
- 济南海关查获禁止进口固体废物23吨
- 简讯:从此闭嘴英文_闭嘴英文
- 高质量发展调研行 | 在智慧港口见证大湾区经济活力——广州南沙港走访一线见闻
- 水的比热容表示什么_水的比热容表
- 将来3月,四大生肖前缘重现,财源滚滚,事业进步
- 运费险需要买吗_运费险是什么意思是不是不用掏运费-微头条
- 微店怎么做链接_微店怎么做
- 前海人寿增值服务持续升级 用心护驾美好生活
- 连云港市约2.58万名考生正式结束高考
- 13只创业板股最新股东户数降逾5% 当前热闻
- 足字旁那个字怎么写(足字旁怎么打)|世界热点评
- 英国监管机构阻止微软收购动视暴雪 后者获准参与上诉程序 全球今热点
- 环球观天下!220件文物讲述汉字源远流长 成博新展带你走进“汉字中国”丨文化和自然遗产日
- 隔离妆前乳和隔离霜的顺序排列(隔离霜 妆前乳 粉底的先后顺序用法) 环球热门
- “峨眉雪芽飘雪”上市,提前为大众送“清凉”-全球观速讯_天天日报
- Linux LED子系统详解
- 鄞州区民政局婚姻登记处上班时间_鄞州区民政局_焦点速看
- 2023年三亚日报 “爱在三亚 情定天涯”公益相亲会今天举行
- 居理买房暴雷!前员工称“欠薪千万元,丈母娘顶替法人”_热点聚焦
- 2023首届装备制造产业大会暨“中国钻机之乡”张家口宣化高质量发展大会准备就绪!
- 全球聚焦:华润集团发声明:“海外华润CRC”等非集团投资公司
- 要闻速递:TheShy素质三连图火了,爆笑流酒桶登场,撞墙空大,随后拿下MVP
- 德云社违反卫生管理, 未取得卫生许可证被罚3万
- 【环球速看料】长安大学学子以“三色”模式助力陕西乡村振兴
- 四川锂矿资源储量占全国总量57% 具备采矿权锂矿储量达1.58亿吨_环球新动态
- 四川建900余个非遗工坊:助文化传承创新 赋能乡村振兴|当前热讯
- 红葡萄酒和白葡萄酒有什么区别?
- 环球头条:50多岁男人的性功能(50岁男人的性能力)
- 单反是什么意思网络用语(单反是什么意思) 天天快消息
- 团伙设下“首付购车”骗局,黄石两家4S店掉进陷阱_世界独家
- 环球快播:环球视点!全球财经连线|专访美国北卡罗来纳大学教堂山分校教授丹尼斯·西蒙:创新驱动中国经济发展-最资讯 世界速讯_天天热头条-全球消息
- 金山云美股涨7.72%|世界快看
- 全球快播:国家乡村振兴局开展农村厕所革命“提质年”
- 助力农产品“飞”向更大市场,如皋磨头镇家庭农场党建联盟电商直播基地启用
- 端午节相关的古诗四句小学_端午节的古诗四句小学? 世界新视野
- 模拟城市!_模拟城市之社会豪华版
- 【世界新视野】6月2日拼多多概念板块涨幅达2%
- wps身份证号码显示e+17怎么恢复_DNF角色恢复系统怎么老是显示 ldquo 抱歉 系统繁忙 请稍后再试 rdquo 我试_世界今亮点
- “拯”个暑假畅玩套装?联想电竞畅玩套装直降2070元!
- 开展应急培训 筑牢公交安全防线_微资讯
- 南阳卧龙区财政局:财政支持“强力度” 企业发展“加速度”
- 环球聚焦:国家矿山安监局发布两起较大瞒报事故处理情况 近百人被问责 相关部门作深刻检查
- 米哈游2022年营收273.4亿元,净利润161.45亿元
- cells是什么意思(cell是什么意思)
- 路的诗句 古诗(路的诗句) 环球快讯
- 化工多品种开工率远低于往年金十期货6月9日讯,今年化工多市场开工率远低于往年 环球关注
- 硅片跌价13% 最低3.2元/片 环球关注
- 普通话考试考什么内容(普通话考试怎么考)
- 新消费观察丨新茶饮跨界“造节”受热捧,柠檬茶赛道今夏或迎大爆发 环球热讯
- 【环球快播报】长春理工大学获赠退役歼教七飞机 将用于科研教学
- 易华录创业板再融资审核状态更新为“审核通过”
- www.jsaisino.com(www aisino sh cn)
- 央行连续7个月 加仓 机构称当前黄金站在十年牛市起点|世界速看
- 海得控制:拟12.78亿元收购行芝达75%股权 并配套募资不超6.97亿元
- 人生总要看一次梅西比赛!《梦幻新诛仙》竟有免费球票,圆梦了
- 广东空调卖爆了 空调加工车间24小时不停歇
- 注意!海得控制将于6月26日召开股东大会
- 全球实时:花落之白虎传说
- 博时富耀一年定开债基金成立
- 上海影城焕新归来 奇谭“小卖部”限时亮相-天天热文
- 吉林车务段真情助力“研学游”
- 养老金调整方案公布了?70岁,75岁,80岁多涨360元,是真的吗?_今日最新
- 【全球播资讯】关注丨重磅!工行、建行、农行、中行、交行、邮储银行同日宣布!
- 焦点速读:开源证券发布家家悦研报 公布股票期权激励计划 激发内部成长动能
- 周小川:上海国际金融中心建设迈出更大步伐需要提升人民币自由兑换度
- 世界快报:2023高考进入第二天,部分地区已公布查分时间
- 微视频|海洋之声
- 焦点速读:家乡的秋天作文800字
- 以“四维八面”司法实践诠释为民情怀|全球聚焦
- 互动| 金百泽:研发了400G光模块PCB关键工艺技术
- 获评江苏银行业保险业普惠金融服务先进单位_每日资讯
- 当前最新:国际油价企稳难挽主题基金颓势 7只原油QDII年内收益全部为负
- 海心桥如何摘金世界人行桥奖?这五大亮点征服评委 焦点播报
- 焦点滚动:隆基绿能:拟投资约125亿元建设单晶硅棒、单晶电池及配套项目
- 聚焦贵马|跑贵马 赏美景 品美食 “六爽”贵阳欢迎你!-快看
- 渌口区计生协多形式开展“5·29会员活动日” 今日精选
- 华立科技:公司游戏游艺设备产品涉及VR技术主要为模拟体验类产品
- 23旭越惠诚2优先A票面利率为2.4200%-环球播资讯
- 创元科技:接受中信建投证券调研
广告
广告
- 各种花样打“功效宣传”擦边球 消炎止血又美白的牙膏真有效吗?
- 黑龙江讷河新增1例确诊4例无症状 病例详情公布
- 浙江宁波余姚奉化宁海三地开展核酸检测 结果均为阴性
- 浙江湖州南浔三处棋牌室经营者被行拘
- 那年今日 | 一张漫画涨知识之12月13日
- 在宁波乘火车跨省出行须持48小时内核酸阴性证明
- 浙江温州一地发现核酸弱阳性?复采复检结果均为阴性
- 浙江三门发现一名密接者:二次核酸检测结果均为阴性
- 贱卖的发电机 新买的制茶机——安徽水电供区改革两周年回访见闻
- 浙江杭州新增1例新冠肺炎确诊病例 为集中隔离人员
- 2022年研考在即,学硕缩招,专硕时代真的来了?
- 探访杭州核酸检测点:排队高峰多在夜间 医院24小时运转
- 浙江发挥零售药店“哨点”作用 织就疫情防控监测网
- 哈尔滨市本轮疫情首批1名确诊患者出院
- 宁波镇海第三轮全员核酸检测574181人 结果均为阴性
- 陕西新增本土确诊病例1例、境外输入无症状感染者2例
- 齐齐哈尔讷河一地调整为中风险地区
- 浙江新增新冠肺炎确诊病例75例 其中本土74例
- 内蒙古新增本土确诊病例5例 均在呼伦贝尔满洲里市
- 黑龙江无新增确诊病例 新增本土核酸检测初筛阳性人员5例










