我正在试验Java 17 Vector孵化器,我决定看看能否为它创建一个零成本的语法糖。下面是我所写内容的一个小片段:
import jdk.incubator.vector._
object VectorOps {
implicit final class FloatVectorOps @inline() (val _this: FloatVector) extends AnyVal {
@inline def +(that: FloatVector): FloatVector = _this.add(that)
@inline def apply(i: Int): Float = _this.lane(i)
}
}
class Test {
def test(x: Float, y: Float): Float = {
import VectorOps._
val SSE = FloatVector.SPECIES_128
val xv = FloatVector.broadcast(SSE, x)
val yv = FloatVector.broadcast(SSE, y)
(xv + yv)(0) // sugar for xv.add(yv).lane(0)
}
}我使用Scala 2.13.5和Java 17。
Scala编译器使用-optimize -opt:inline -opt-warnings:at-inline-failed -Yopt-inline-heuristics:at-inline-annotated -opt:nullness-tracking -opt:box-unbox -opt:copy-propagation -opt:unreachable-code -language:implicitConversions -opt:closure-invocations运行。
JVM是用--add-modules jdk.incubator.vector运行的。
但是,Scala编译器将test方法的最后一行编译为
GETSTATIC VectorOps$FloatVectorOps$.MODULE$ : LVectorOps$FloatVectorOps$;
POP
GETSTATIC VectorOps$.MODULE$ : LVectorOps$;
GETSTATIC VectorOps$FloatVectorOps$.MODULE$ : LVectorOps$FloatVectorOps$;
POP
GETSTATIC VectorOps$.MODULE$ : LVectorOps$;
ALOAD 4
INVOKEVIRTUAL VectorOps$.FloatVectorOps (Ljdk/incubator/vector/FloatVector;)Ljdk/incubator/vector/FloatVector;
ALOAD 5
INVOKEVIRTUAL jdk/incubator/vector/FloatVector.add (Ljdk/incubator/vector/Vector;)Ljdk/incubator/vector/FloatVector;
INVOKEVIRTUAL VectorOps$.FloatVectorOps (Ljdk/incubator/vector/FloatVector;)Ljdk/incubator/vector/FloatVector;
ICONST_0
INVOKEVIRTUAL jdk/incubator/vector/FloatVector.lane (I)F
FRETURN这些对隐式类构造函数的调用完全抛出Hotspot,它无法打开向量变量,从而降低性能。注意,就字节码而言,隐式类构造函数是一个标识函数,这实际上意味着它是一个非操作函数。使用MODULE$的所有东西也是不必要的。但是Hotspot没有看到它。
(请注意,对+和apply的方法调用已成功内联。)
添加-Yopt-inline-heuristics:everything移除构造函数调用和MODULE$,并修复性能,但这就像使用大锤破解一个螺母一样。就像一把大锤,感觉不安全。
当然,用Java风格编写整个代码也可以改善性能,但这并不是重点。
所以我的问题是:
-Yopt-inline-heuristics:everything的情况下消除调用,并且无需重写原始-Yopt-inline-heuristics:everything语法中的所有内容吗?发布于 2022-09-28 19:49:35
我想出了一个解决方案:宏。
object VectorOps {
implicit final class FloatVectorOps @inline() (val _this: FloatVector) extends AnyVal {
@inline def +(that: FloatVector): FloatVector = macro MacroVectorOps.add
@inline def apply(i: Int): Float = macro MacroVectorOps.lane
}
}
object MacroVectorOps {
import scala.reflect.macros.blackbox
def add(c: blackbox.Context)(that: c.Tree): c.Tree = {
import c.universe._
// deconstruct the implicit conversion:
val q"$conv($in)" = c.prefix.tree
q"$in.add($that)"
}
def lane(c: blackbox.Context)(i: c.Tree): c.Tree = {
import c.universe._
val q"$conv($in)" = c.prefix.tree
q"$in.lane($i)"
}
}使用它的代码编译成高效的字节码,就像我使用原始Java编写它一样,字节码中根本没有FloatVectorOps类或VectorOps对象的痕迹。
https://stackoverflow.com/questions/70656216
复制相似问题