# Better sqrt

**URL:** <https://discourse.vtk.org/t/better-sqrt/3460>\
**Category:** Development\
**Created:** [June 3, 2020, 5:59pm UTC](https://discourse.vtk.org/t/better-sqrt/3460 "2020-06-03T17:59:45Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ron84](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ron84/32/630_2.png) [@Ron84](https://discourse.vtk.org/u/Ron84)\
**Post date:** [June 3, 2020, 5:59pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/1 "2020-06-03T17:59:46Z")

</div>

Is someone able to translate the sqrt14-function into asm of gcc?

```cpp
double inline __declspec (naked)__fastcall sqrt14(double n)
{
	_asm fld qword ptr [esp+4]
	_asm fsqrt
	_asm ret 8
} 

```

Reference: [https://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi](https://www.codeproject.com/Articles/69941/Best-Square-Root-Method-Algorithm-Function-Precisi)

---

<div class="post-metadata">

**Author:** ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)\
**Post date:** [June 3, 2020, 8:53pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/2 "2020-06-03T20:53:48Z")

</div>

For gcc, the sqrt() function is already a compiler intrinsic. By default, gcc produces an SSE `sqrtsd` instruction when you call sqrt(). The `fsqrt` in your example is actually the old pre-SSE instruction. You can force gcc to produce it by turning off SSE (with the `-mfpmath=387` option) but the SSE variant is probably faster.

The article you linked is 10 years old and intended for 32-bit Windows programmers, I don’t think it’s applicable to modern 64-bit CPUs and compilers.

---

<div class="post-metadata">

**Author:** ![seanm](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/s/a88e4f/32.png) [@seanm](https://discourse.vtk.org/u/seanm)\
**Post date:** [June 3, 2020, 8:53pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/3 "2020-06-03T20:53:54Z")

</div>

That article is a full decade old. Compilers are much better now. Are you sure that sqrt14 is still better today? Playing with [godbolt.org](http://godbolt.org) it looks to me like gcc generates something very similar already.

---

<div class="post-metadata">

**Author:** ![Ron84](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ron84/32/630_2.png) [@Ron84](https://discourse.vtk.org/u/Ron84)\
**Post date:** [June 3, 2020, 9:11pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/4 "2020-06-03T21:11:32Z")

</div>

It was just an idea. I would like to replace vtkMath::Normalize, because it is too slow for my use-case. It is too slow on my old Core2Duo…

---

<div class="post-metadata">

**Author:** ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)\
**Post date:** [June 3, 2020, 9:24pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/5 "2020-06-03T21:24:08Z")

</div>

There is a CPU instruction specifically designed to accelerate normalization:

```auto
RSQRTSS

```

It computes `1/sqrt(x)` so that the divisions aren’t necessary, and it uses single-precision floats. I’d be very interested to see how much it can speed things up. I don’t know if there is an easy way to get gcc to produce this instruction.

---

<div class="post-metadata">

**Author:** ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)\
**Post date:** [June 3, 2020, 9:48pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/6 "2020-06-03T21:48:39Z")

</div>

Actually, gcc automatically produces `RSQRTSS` if the `-ffast-math` option is used:

`g++-10 -O3 -mfpmath=sse -ffast-math -S normalize.cxx -o normalize.a`

code for normalize.cxx:

```auto
#include <cmath>

void normalize(float x[3])
{
  float f = 1.0f/std::sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
  x[0] *= f;
  x[1] *= f;
  x[2] *= f;
}

```

produced assembly code:

```auto
_Z9normalizePf:
	movss	(%rdi), %xmm4
	movss	4(%rdi), %xmm3
	movss	8(%rdi), %xmm2
	movaps	%xmm4, %xmm1
	movaps	%xmm3, %xmm0
	mulss	%xmm3, %xmm0
	mulss	%xmm4, %xmm1
	addss	%xmm0, %xmm1
	movaps	%xmm2, %xmm0
	mulss	%xmm2, %xmm0
	addss	%xmm1, %xmm0
	movaps	%xmm0, %xmm5
	rsqrtss	%xmm5, %xmm5 # here it is
	mulss	%xmm5, %xmm0
	mulss	%xmm5, %xmm0
	mulss	.LC1(%rip), %xmm5
	addss	.LC0(%rip), %xmm0
	mulss	%xmm5, %xmm0
	mulss	%xmm0, %xmm4
	mulss	%xmm0, %xmm3
	mulss	%xmm2, %xmm0
	movss	%xmm4, (%rdi)
	movss	%xmm3, 4(%rdi)
	movss	%xmm0, 8(%rdi)
	ret
	.align 4
.LC0:
	.long	3225419776
	.align 4
.LC1:
	.long	3204448256

```

So gcc slips in a couple extra instructions to try to improve upon the precision of `RSQRTSS`, but overall the code is pretty tight. Just make sure to compile with the `-mfpmath=sse`, `-msse` and `-ffast-math` options, and use gcc 5 or later.

---

<div class="post-metadata">

**Author:** ![seanm](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/s/a88e4f/32.png) [@seanm](https://discourse.vtk.org/u/seanm)\
**Post date:** [June 3, 2020, 10:23pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/7 "2020-06-03T22:23:21Z")

</div>

[goldbolt.org](http://goldbolt.org) is really fun for this kind of stuff, we can see that the compiler is very sensitive sometimes. Using 1.0f vs 1.0 generates different code with gcc, though not with clang:

[https://godbolt.org/z/HRVgtm](https://godbolt.org/z/HRVgtm)

It’s not immediately clear which of these is faster at run time, and RSQRTSS has less precision.

Sean

---

<div class="post-metadata">

**Author:** ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)\
**Post date:** [June 3, 2020, 10:33pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/8 "2020-06-03T22:33:10Z")

</div>

According to e.g. the AMD RYZEN spec sheet, `RSQRTSS` has five time the throughput of `SQRTSS`, so you lose some precision but you gain a lot of speed. Also the divisions becomes unnecessary, and the throughput of `MULSS` is at least three times the throughput of `DIVSS`.

So I’d be very interested to see what the real-world performance is, because in theory it’s pretty good.

---

<div class="post-metadata">

**Author:** ![seanm](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/s/a88e4f/32.png) [@seanm](https://discourse.vtk.org/u/seanm)\
**Post date:** [June 3, 2020, 11:02pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/9 "2020-06-03T23:02:04Z")

</div>

There’s no double precision variant, is there?

---

<div class="post-metadata">

**Author:** ![seanm](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/s/a88e4f/32.png) [@seanm](https://discourse.vtk.org/u/seanm)\
**Post date:** [June 3, 2020, 11:37pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/10 "2020-06-03T23:37:45Z")

</div>

So playing with godbolt more, clang seems to already generate rsqrtss with today’s VTK code (even though vtk uses division and not multiplication!), but I can only convince gcc to use it if you don’t return the norm from Normalize():

[https://godbolt.org/z/zenyAc](https://godbolt.org/z/zenyAc)

Sean

---

<div class="post-metadata">

**Author:** ![ben.boeckel](https://discourse.vtk.org/letter_avatar_proxy/v4/letter/b/ea5d25/32.png) [@ben.boeckel](https://discourse.vtk.org/u/ben.boeckel)\
**Post date:** [June 4, 2020, 1:51am UTC](https://discourse.vtk.org/t/better-sqrt/3460/11 "2020-06-04T01:51:56Z")

</div>

> [@dgobbi](#):
>
> -ffast-math

Just a note that this flag makes VTK ABI incompatible with any code passing floats and doubles across its API boundaries (which are a lot of places). It does this by basically ignoring what C and C++ require floating point types to do in various situation. Instead, maybe some of [the things it does](https://stackoverflow.com/a/22135559) can be hinted at/handled in VTK code explicitly?

---

<div class="post-metadata">

**Author:** ![Ron84](https://discourse.vtk.org/user_avatar/discourse.vtk.org/ron84/32/630_2.png) [@Ron84](https://discourse.vtk.org/u/Ron84)\
**Post date:** [June 4, 2020, 3:39pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/12 "2020-06-04T15:39:03Z")

</div>

A good question!

---

<div class="post-metadata">

**Author:** ![dgobbi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dgobbi/32/18_2.png) [@dgobbi](https://discourse.vtk.org/u/dgobbi)\
**Post date:** [June 4, 2020, 4:12pm UTC](https://discourse.vtk.org/t/better-sqrt/3460/13 "2020-06-04T16:12:09Z")

</div>

There is no double-precision version. According to [this stackoverflow discussion](https://stackoverflow.com/questions/1528727/why-is-sse-scalar-sqrtx-slower-than-rsqrtx-x) the `rsqrtss` instruction by itself provides only 11 accurate bits, much less than even the 24-bit mantissa of a single-precision float.
