On Thu, Aug 3, 2017 at 7:17 PM, Karl Wagner <razie...@gmail.com> wrote:
> > On 3. Aug 2017, at 20:52, Taylor Swift via swift-evolution < > swift-evolution@swift.org> wrote: > > In an effort to get this thread back on track, I tried implementing > cos(_:) in pure generic Swift code, with the BinaryFloatingPoint protocol. > It deviates from the _cos(_:) intrinsic by no more than > 5.26362703423544e-11. Adding more terms to the approximation only has a > small penalty to the performance for some reason. > > To make the benchmarks fair, and explore the idea of distributing a Math > module without killing people on the cross-module optimization boundary, I > enabled some of the unsafe compiler attributes. All of these benchmarks are > cross-module calls, as if the math module were downloaded as a dependency > in the SPM. > > == Relative execution time (lower is better) == > > llvm intrinsic : 3.133 > glibc cos() : 3.124 > > no attributes : 43.675 > with specialization : 4.162 > with inlining : 3.108 > with inlining and specialization : 3.264 > > As you can see, the pure Swift generic implementation actually beats the > compiler intrinsic (and the glibc cos() but I guess they’re the same thing) > when inlining is used, but for some reason generic specialization and > inlining don’t get along very well. > > Here’s the source implementation. It uses a taylor series (!) which > probably isn’t optimal but it does prove that cos() and sin() can be > implemented as generics in pure Swift, be distributed as a module outside > the stdlib, and still achieve competitive performance with the llvm > intrinsics. > > @_inlineable > //@_specialize(where F == Float) > //@_specialize(where F == Double) > public > func cos<F>(_ x:F) -> F where F:BinaryFloatingPoint > { > let x:F = abs(x.remainder(dividingBy: 2 * F.pi)), > quadrant:Int = Int(x * (2 / F.pi)) > > switch quadrant > { > case 0: > return cos(on_first_quadrant: x) > case 1: > return -cos(on_first_quadrant: F.pi - x) > case 2: > return -cos(on_first_quadrant: x - F.pi) > case 3: > return -cos(on_first_quadrant: 2 * F.pi - x) > default: > fatalError("unreachable") > } > } > > @_versioned > @_inlineable > //@_specialize(where F == Float) > //@_specialize(where F == Double) > func cos<F>(on_first_quadrant x:F) -> F where F:BinaryFloatingPoint > { > let x2:F = x * x > var y:F = -0.0000000000114707451267755432394 > for c:F in [0.000000002087675698165412591559, > -0.000000275573192239332256421489, > 0.00002480158730158702330045157, > -0.00138888888888888880310186415, > 0.04166666666666666665319411988, > -0.4999999999999999999991637437, > 0.9999999999999999999999914771 > ] > { > y = x2 * y + c > } > return y > } > > On Thu, Aug 3, 2017 at 7:04 AM, Stephen Canon via swift-evolution < > swift-evolution@swift.org> wrote: > >> On Aug 2, 2017, at 7:03 PM, Karl Wagner via swift-evolution < >> swift-evolution@swift.org> wrote: >> >> >> It’s important to remember that computers are mathematical machines, and >> some functions which are implemented in hardware on essentially every >> platform (like sin/cos/etc) are definitely best implemented as compiler >> intrinsics. >> >> >> sin/cos/etc are implemented in software, not hardware. x86 does have the >> FSIN/FCOS instructions, but (almost) no one actually uses them to implement >> the sin( ) and cos( ) functions; they are a legacy curiosity, both too slow >> and too inaccurate for serious use today. There are no analogous >> instructions on ARM or PPC. >> >> – Steve >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >> >> > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution > > > > Just a guess, but I’d expect inlining implies specialisation. It would be > weird if the compiler inlined a chunk of unoptimised generic code in to > your function. > > Pretty cool figures, though. > > - Karl > > The weird part is that generic specialization actually *hurt* performance. I understand why inlining can be harmful sometimes, but I always assumed specialization was always helpful. Weird. Can a core team member weigh in here?
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution