PAC2017小经历(二)

PAC2017小经历(二)

前一段时间沉迷于各种实验、报告(以及塞尔达),现在终于有了时间想起来这个博客就这样烂尾了。。现在赶紧在残存的记忆中再写一些东西上去。。

向量化(Vectorization)

KNL平台的CPU支持AVX-512的向量操作,也就是说对于它来说,可以同时操作8*8个double数的运算。这样的操作显然是并行运算中所需要的,于是在这次比赛中,我们便试着对程序进行了向量化改写。这个改写阶段大致分为两个部分:失败、低效的手动改写以及莫名其妙很厉害的自动向量化(就是加了一个参数)。

手动改写

手动改写就是说在英特尔官方提供的指令指导下,一条一条地改写所有的加减乘除法。下面大致记录一下遇见的两个问题。

英特尔官方IntrinsicsGuide

  1. 所读入的数据是一个二维数组,这个二维数组每一行的数据是我们需要进行向量化的(因为这样才方便写)。然而每一行的长度多半不是8的倍数,那么剩下的一小截怎么处理。

我们用了两种方法来解决这个问题。

第一种方法是将剩下的一小截补齐到8的倍数,然后再一视同仁地使用向量化全部计算。实际做的时候发现,这样是很不可取的,因为二维数组是连续的,想要在每一行的末尾进行补齐所需要做的内存搬运工作很大,需要N次操作,会浪费掉很多的时间。实际上写下来,测试了一下也确实反而慢了更多。

第二种方法是干脆将剩下的元素丢弃了,就用普通的指令集进行处理就行。虽然感觉这样做也不是很好,不过最后测试出来速度是要快一点。

可能的第三种方法,将整个二维数组全部一起向量化,使得只有最后一个多余的尾巴即可,这样只需要1次操作就可以了。但是实现难度可以说是比较大了。。当时一时半会不知道怎么做,就放弃了。

  1. 程序中包含了大量的分支判断,向量化操作并不能必须多个元素同时进行分支。

改写代码的时候,尽可能的消去了分支。然后通过同时计算在不同的分支下的所有的数据的结果,然后最后通过mask move来进行相应的传输。经过观察,该程序的分支最多只有三个,也就是说相对来说应该是会有一定的优化效果的,不过由于改写量巨大、debug难度更大,导致了计划的搁浅。。

自动改写

说白了,就是加上这个-xMIC-AVX512以及-qopt-report=5,这样编译之后会有一个向量化报告,根据向量化报告进行修改即可。。。。不过在此之前,还是要做一些尽可能的内存对齐,据说不对齐的向量化会降低20%的效率。

具体对齐的方法有点多,只能甩下一个链接

英特尔官方解答

最终

在编译器优秀的自动向量化之后,程序速度得到了飞跃般的提升,不过离最终结果还是有一点差距的。。之后的优化只能今后有机会再记录一下了。。

Powered by Hexo and Hexo-theme-hiker

Copyright © 2013 - 2018 Alex's Blog All Rights Reserved.

Yifeng Tang hält Urheberrechtsansprüche.