从Lucene 8.4.0开始,在写入/读取倒排信息时,即写入/读取索引文件.doc、.pos、.pay时,通过巧妙的编码方式(下文中展开)使得C2编译器能生成SIMD(Single Instruction Multiple Data)指令,从而提高了写入/读取速度。
SIMD(Single Instruction Multiple Data)
下文中关于SIMD的介绍基于以下的一些资料,如果链接失效,可以阅读文章底部附件中的备份:
- 文章一:http://www1.cs.columbia.edu/~kar/pubsk/simd.pdf
- 文章二:http://daniel-strecker.com/blog/2020-01-14_auto_vectorization_in_java/#Output%20Interpretation
- 文章三:http://www.songho.ca/misc/sse/sse.html
- 文章四:https://stackoverflow.com/questions/59725341/java-auto-vectorization-example
- 文章五:https://en.wikipedia.org/wiki/SIMD
- 文章六:https://prestodb.rocks/code/simd
由于本人在指令集方面有限的知识储备,只能泛泛而谈,无法准确识别上文中可能出现的错误,欢迎该方面的大佬勘误。如果能将勘误内容写到https://github.com/LuXugang/Lucene-7.5.0的issue中就更好啦。
SIMD指令集使得CPU能同时对多个值执行相同的操作:
图1:
图1选自论文http://www1.cs.columbia.edu/~kar/pubsk/simd.pdf。 上图中,X、Y的值存放在128bit的寄存器中,其中X、Y的值占32bit。通过SIMD,使得可以同时计算四次运算(operand)。
自动向量化(Automatic Vectorization)
先贴出Wiki的原文:
1
Automatic vectorization, in parallel computing, is a special case of automatic parallelization, where a computer program is converted from a scalar implementation, which processes a single pair of operands at a time, to a vector implementation, which processes one operation on multiple pairs of operands at once
上文的大意为在一次处理过程中,由只能执行一对运算(operand)变成执行多对运算成为自动向量化。
在写完一个Java程序后,Java代码会被编译为字节码并且存放到class文件中,随后在运行之前或运行期间,字节码将再次被编译。这次字节码将被编译为机器码(native machine code)这个过程即JIT编译。
不同于C/C++,在编写Java代码时,没有显示的接口或者方式来指定向量计算,在Java中,完全是通过C2编译器来判断某段代码是否需要向量化。
SIMD In Java
Java程序中,可以通过指定虚拟机参数查看运行期间生成的汇编指令。
虚拟机参数
添加两个虚拟机参数:-XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly。
另外需要下载hsdis-amd64.dylib(见附件),在Mac系统中,并将其放到/Library/Java/JavaVirtualMachines/jdk-12.jdk/Contents/Home/lib
目录中即可。
剩余内容看这里:https://www.amazingkoala.com.cn/Lucene/Codecs/2021/0115/187.html