GMP 4.3 multiplication performance

Torbjorn Granlund tg at gmplib.org
Wed Jun 3 13:35:41 CEST 2009


nisse at lysator.liu.se (Niels Möller) writes:

  Torbjorn Granlund <tg at gmplib.org> writes:
  
  > This particular macro is not currently problem free.  Let's compare
  > lshift+add_n and submul_1 on some machines:
  >
  >              lshift+sub_n            submul_1
  > athlon64        3.87                     2.5
  > core2           3.3                      4.5
  > pentium4/64     7.3                     14.9
  > ultrasparc 3    7.75                    23
  > power4/ppc970   5.0                     10
  
  So of these, submul_1 is a decent alternative only on athlon64. I was
  just about to ask. Is submul_1 limited by the multiplier or the carry
  recurrency? In the latter case, I imagine there's no point in
  implementing a separate sub_lshift there.
  
The decode bandwidth limits athlon64 submul_1 performance.  If decode
bandwidth were unlimited, the multiply hardware unit would limit
performance to 2 c/l (it has a repeat rate of 1/2).  If the multiply
unit were infinitely powerful, carry recurrency will limit performance
to 1 c/l...

  > My solution is that we write mpn_sublsh_n for machines we care about, or
  > that we define a USE_SUBMUL_1_FOR_SUB_LSHIFT in tune/tuneup.c.
  
  And then one would put
  
  #if USE_SUBMUL_1_FOR_SUB_LSHIFT
  # define mpn_sub_lshift(...) mpn_submul(...)
  # define HAVE_NATIVE_mpn_lshift
  #endif
  
  in gmp-impl.h, so that code using it need only check for
  HAVE_NATIVE_mpn_lshift, right?

That seems somewhat unorthodox.

Why override HAVE_NATIVE_mpn_lshift with a new meaning (and what should
defining it to empty mean, that it exists or that it does not exist?)?

To what should mpn_sub_lshift default?

  > These might be tricky to get fast on x86, though.  One problem is that a
  > non-constant general register shift count must reside in the
  > rcx/ecx/cx/cl register, which means we need to alternate it between cnt
  > and 64-cnt in the loop.  (Alternatively use could use MMX/SSE shift
  > operation.)
  
  Annoying restriction, that. But since top bits are ignored, two
  negation instructions in the loop should be sufficient to switch back
  and forth between those values.
  
Sure possible (My experience is that wasting two registers allows freer
OoO execution.)

  > It should be renamed add_sub_n or perhaps add_n_sub_n, to avoid
  > breaching the naming scheme.
  
  Or "butterfly", unless you see a need to have a large family of
  functions that compute two things in parallel.
  
We should allow the GMP assembly madness full freedom.  :-)

-- 
Torbjörn


More information about the gmp-devel mailing list