So I'm doing some performance optimization on my GameMath package and I'm having trouble understanding compiler hints.
I'm not sure what @_transparent
is doing, because adding it to this operator makes it way faster; so much so that it's significantly faster then using simd on macOS x86_64 when using the operator in a performance test.
This is the test
func testMultiplicationPerformance() {
let m1 = Transform3<Float>(position: Position3(128, 128, 128),
rotation: Quaternion(Degrees(128), axis: .up),
scale: .one).createMatrix()
let m2 = Transform3<Float>(position: Position3(0, 1, 2),
rotation: Quaternion(Degrees(90), axis: .up),
scale: Size3(-100, -15, -1)).createMatrix()
let m3 = Transform3<Float>(position: Position3(-128, -128, -128),
rotation: Quaternion(Degrees(-65), axis: .up),
scale: Size3(100, 15, 1)).createMatrix()
func doMath() {
var mtx: Matrix4x4<Float> = .identity
mtx *= m1 * m2 * m3
mtx *= m1 * m2 * m3
mtx *= m1 * m2 * m3
mtx *= m1 * m2 * m3
func more() -> Matrix4x4<Float> {
return m1 * m2 * m3
}
for _ in 1 ..< 5000 {
mtx *= more()
mtx *= more()
}
for _ in 1 ..< 5000 {
mtx *= more()
}
}
measure {
doMath()
}
}
I thought @_transparent
was a heavy-handed @inlineable
, but it makes my raw Swift operator nearly 10x faster than using the same code with @inlinable
/ @inline(__always)
. It's faster in unoptimized and optimized builds.
Is @_transparent
somehow making the compiler do better vectorization? Or is the speed coming from something else?
Also worth noting, using @_transparent
on the simd implementation of the operator had no significant performance change. Using raw Swift with @_transparent
was the fastest in all of my tests.
This is the SIMD operator Implementation
static func *=(lhs: inout Self, rhs: Self) {
let r = simd_mul(simd_float4x4(lhs.storage[0], lhs.storage[1], lhs.storage[2], lhs.storage[3]),
simd_float4x4(rhs.storage[0], rhs.storage[1], rhs.storage[2], rhs.storage[3]))
lhs.storage[0] = r[0]
lhs.storage[1] = r[1]
lhs.storage[2] = r[2]
lhs.storage[3] = r[3]
}