README
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:19k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. Copyright 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
  2. This file is part of the GNU MP Library.
  3. The GNU MP Library is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU Lesser General Public License as published by
  5. the Free Software Foundation; either version 3 of the License, or (at your
  6. option) any later version.
  7. The GNU MP Library is distributed in the hope that it will be useful, but
  8. WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  9. or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  10. License for more details.
  11. You should have received a copy of the GNU Lesser General Public License
  12. along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  13.                GMP SPEED MEASURING AND PARAMETER TUNING
  14. The programs in this directory are for knowledgeable users who want to
  15. measure GMP routines on their machine, and perhaps tweak some settings or
  16. identify things that can be improved.
  17. The programs here are tools, not ready to run solutions.  Nothing is built
  18. in a normal "make all", but various Makefile targets described below exist.
  19. Relatively few systems and CPUs have been tested, so be sure to verify that
  20. results are sensible before relying on them.
  21. MISCELLANEOUS NOTES
  22. --enable-assert
  23.     Don't configure with --enable-assert, since the extra code added by
  24.     assertion checking may influence measurements.
  25. Direct mapped caches
  26.     Some effort has been made to accommodate CPUs with direct mapped caches,
  27.     by putting data blocks more or less contiguously on the stack.  But this
  28.     will depend on TMP_ALLOC using alloca, and even then it may or may not
  29.     be enough.
  30. FreeBSD 4.2 i486 getrusage
  31.     This getrusage seems to be a bit doubtful, it looks like it's
  32.     microsecond accurate, but sometimes ru_utime remains unchanged after a
  33.     time of many microseconds has elapsed.  It'd be good to detect this in
  34.     the time.c initializations, but for now the suggestion is to pretend it
  35.     doesn't exist.
  36.         ./configure ac_cv_func_getrusage=no
  37. NetBSD 1.4.1 m68k macintosh time base
  38.     On this system it's been found getrusage often goes backwards, making it
  39.     unusable (time.c getrusage_backwards_p detects this).  gettimeofday
  40.     sometimes doesn't update atomically when it crosses a 1 second boundary.
  41.     Not sure what to do about this.  Expect possible intermittent failures.
  42. SCO OpenUNIX 8 /etc/hw
  43.     /etc/hw takes about a second to return the cpu frequency, which suggests
  44.     perhaps it's measuring each time it runs.  If this is annoying when
  45.     running the speed program repeatedly then set a GMP_CPU_FREQUENCY
  46.     environment variable (see TIME BASE section below).
  47. Timing on GNU/Linux
  48.     On Linux, timing currently uses the cycle counter. This is unreliable,
  49.     since the counter is not saved and restored at context switches (unlike
  50.     FreeBSD and Solaris where the cycle counter is "virtualized").
  51.     Using the clock_gettime method with CLOCK_PROCESS_CPUTIME_ID (posix) or
  52.     CLOCK_VIRTUAL (BSD) should be more reliable. To get clock_gettime
  53.     with glibc, one has to link with -lrt (which also drags in the pthreads
  54.     threading library). configure.in must be hacked to detect this and
  55.     arrange proper linking. Something like
  56.       old_LIBS="$LIBS"
  57.       AC_SEARCH_LIBS(clock_gettime, rt, [AC_DEFINE(HAVE_CLOCK_GETTIME)])
  58.       TUNE_LIBS="$LIBS"
  59.       LIBS="$old_LIBS"
  60.       AC_SUBST(TUNE_LIBS)
  61.     
  62.     might work.
  63. Low resolution timebase
  64.     Parameter tuning can be very time consuming if the only timebase
  65.     available is a 10 millisecond clock tick, to the point of being
  66.     unusable.  This is currently the case on VAX and ARM systems.
  67. PARAMETER TUNING
  68. The "tuneup" program runs some tests designed to find the best settings for
  69. various thresholds, like MUL_TOOM22_THRESHOLD.  Its output can be put
  70. into gmp-mparam.h.  The program is built and run with
  71.         make tune
  72. If the thresholds indicated are grossly different from the values in the
  73. selected gmp-mparam.h then there may be a performance boost in applicable
  74. size ranges by changing gmp-mparam.h accordingly.
  75. Be sure to do a full reconfigure and rebuild to get any newly set thresholds
  76. to take effect.  A partial rebuild is enough sometimes, but a fresh
  77. configure and make is certain to be correct.
  78. If a CPU has specific tuned parameters coming from a gmp-mparam.h in one of
  79. the mpn subdirectories then the values from "make tune" should be similar.
  80. But check that the configured CPU is right and there are no machine specific
  81. effects causing a difference.
  82. It's hoped the compiler and options used won't have too much effect on
  83. thresholds, since for most CPUs they ultimately come down to comparisons
  84. between assembler subroutines.  Missing out on the longlong.h macros by not
  85. using gcc will probably have an effect.
  86. Some thresholds produced by the tune program are merely single values chosen
  87. from what's a range of sizes where two algorithms are pretty much the same
  88. speed.  When this happens the program is likely to give somewhat different
  89. values on successive runs.  This is noticeable on the toom3 thresholds for
  90. instance.
  91. SPEED PROGRAM
  92. The "speed" program can be used for measuring and comparing various
  93. routines, and producing tables of data or gnuplot graphs.  Compile it with
  94. make speed
  95. (Or on DOS systems "make speed.exe".)
  96. Here are some examples of how to use it.  Check the code for all the
  97. options.
  98. Draw a graph of mpn_mul_n, stepping through sizes by 10 or a factor of 1.05
  99. (whichever is greater).
  100.         ./speed -s 10-5000 -t 10 -f 1.05 -P foo mpn_mul_n
  101. gnuplot foo.gnuplot
  102. Compare mpn_add_n and an mpn_lshift by 1, showing times in cycles and
  103. showing under mpn_lshift the difference between it and mpn_add_n.
  104. ./speed -s 1-40 -c -d mpn_add_n mpn_lshift.1
  105. Using option -c for times in cycles is interesting but normally only
  106. necessary when looking carefully at assembler subroutines.  You might think
  107. it would always give an integer value, but this doesn't happen in practice,
  108. probably due to overheads in the time measurements.
  109. In the free-form output the "#" symbol against a measurement means the
  110. corresponding routine is fastest at that size.  This is a convenient visual
  111. cue when comparing different routines.  The graph data files <name>.data
  112. don't get this since it would upset gnuplot or other data viewers.
  113. TIME BASE
  114. The time measuring method is determined in time.c, based on what the
  115. configured host has available.  A cycle counter is preferred, possibly
  116. supplemented by another method if the counter has a limited range.  A
  117. microsecond accurate getrusage() or gettimeofday() will work quite well too.
  118. The cycle counters (except possibly on alpha) and gettimeofday() will depend
  119. on the machine being otherwise idle, or rather on other jobs not stealing
  120. CPU time from the measuring program.  Short routines (those that complete
  121. within a timeslice) should work even on a busy machine.
  122. Some trouble is taken by speed_measure() in common.c to avoid ill effects
  123. from sporadic interrupts, or other intermittent things (like cron waking up
  124. every minute).  But generally an idle machine will be necessary to be
  125. certain of consistent results.
  126. The CPU frequency is needed to convert between cycles and seconds, or for
  127. when a cycle counter is supplemented by getrusage() etc.  The speed program
  128. will convert as necessary according to the output format requested.  The
  129. tune program will work with either cycles or seconds.
  130. freq.c knows how to get the frequency on some systems, or can measure a
  131. cycle counter against gettimeofday() or getrusage(), but when that fails, or
  132. needs to be overridden, an environment variable GMP_CPU_FREQUENCY can be
  133. used (in Hertz).  For example in "bash" on a 650 MHz machine,
  134. export GMP_CPU_FREQUENCY=650e6
  135. A high precision time base makes it possible to get accurate measurements in
  136. a shorter time.
  137. EXAMPLE COMPARISONS - VARIOUS
  138. Here are some ideas for things that can be done with the speed program.
  139. There's always going to be a certain amount of overhead in the time
  140. measurements, due to reading the time base, and in the loop that runs a
  141. routine enough times to get a reading of the desired precision.  Noop
  142. functions taking various arguments are available to measure this.  The
  143. "overhead" printed by the speed program each time in its intro is the "noop"
  144. routine, but note that this is just for information, it isn't deducted from
  145. the times printed or anything.
  146. ./speed -s 1 noop noop_wxs noop_wxys
  147. To see how many cycles per limb a routine is taking, look at the time
  148. increase when the size increments, using option -D.  This avoids fixed
  149. overheads in the measuring.  Also, remember many of the assembler routines
  150. have unrolled loops, so it might be necessary to compare times at, say, 16,
  151. 32, 48, 64 etc to see what the unrolled part is taking, as opposed to any
  152. finishing off.
  153.         ./speed -s 16-64 -t 16 -C -D mpn_add_n
  154. The -C option on its own gives cycles per limb, but is really only useful at
  155. big sizes where fixed overheads are small compared to the code doing the
  156. real work.  Remember of course memory caching and/or page swapping will
  157. affect results at large sizes.
  158.         ./speed -s 500000 -C mpn_add_n
  159. Once a calculation stops fitting in the CPU data cache, it's going to start
  160. taking longer.  Exactly where this happens depends on the cache priming in
  161. the measuring routines, and on what sort of "least recently used" the
  162. hardware does.  Here's an example for a CPU with a 16kbyte L1 data cache and
  163. 32-bit limb, showing a suddenly steeper curve for mpn_add_n at about 2000
  164. limbs.
  165.         ./speed -s 1-4000 -t 5 -f 1.02 -P foo mpn_add_n
  166. gnuplot foo.gnuplot
  167. When a routine has an unrolled loop for, say, multiples of 8 limbs and then
  168. an ordinary loop for the remainder, it can happen that it's actually faster
  169. to do an operation on, say, 8 limbs than it is on 7 limbs.  The following
  170. draws a graph of mpn_sub_n, to see whether times smoothly increase with
  171. size.
  172.         ./speed -s 1-100 -c -P foo mpn_sub_n
  173. gnuplot foo.gnuplot
  174. If mpn_lshift and mpn_rshift have special case code for shifts by 1, it
  175. ought to be faster (or at least not slower) than shifting by, say, 2 bits.
  176.         ./speed -s 1-200 -c mpn_rshift.1 mpn_rshift.2
  177. An mpn_lshift by 1 can be done by mpn_add_n adding a number to itself, and
  178. if the lshift isn't faster there's an obvious improvement that's possible.
  179.         ./speed -s 1-200 -c mpn_lshift.1 mpn_add_n_self
  180. On some CPUs (AMD K6 for example) an "in-place" mpn_add_n where the
  181. destination is one of the sources is faster than a separate destination.
  182. Here's an example to see this.  ".1" selects dst==src1 for mpn_add_n (and
  183. mpn_sub_n), for other values see speed.h SPEED_ROUTINE_MPN_BINARY_N_CALL.
  184.         ./speed -s 1-200 -c mpn_add_n mpn_add_n.1
  185. The gmp manual points out that divisions by powers of two should be done
  186. using a right shift because it'll be significantly faster than an actual
  187. division.  The following shows by what factor mpn_rshift is faster than
  188. mpn_divrem_1, using division by 32 as an example.
  189.         ./speed -s 10-20 -r mpn_rshift.5 mpn_divrem_1.32
  190. EXAMPLE COMPARISONS - MULTIPLICATION
  191. mul_basecase takes a ".<r>" parameter which is the first (larger) size
  192. parameter.  For example to show speeds for 20x1 up to 20x15 in cycles,
  193.         ./speed -s 1-15 -c mpn_mul_basecase.20
  194. mul_basecase with no parameter does an NxN multiply, so for example to show
  195. speeds in cycles for 1x1, 2x2, 3x3, etc, up to 20x20, in cycles,
  196.         ./speed -s 1-20 -c mpn_mul_basecase
  197. sqr_basecase is implemented by a "triangular" method on most CPUs, making it
  198. up to twice as fast as mul_basecase.  In practice loop overheads and the
  199. products on the diagonal mean it falls short of this.  Here's an example
  200. running the two and showing by what factor an NxN mul_basecase is slower
  201. than an NxN sqr_basecase.  (Some versions of sqr_basecase only allow sizes
  202. below SQR_TOOM2_THRESHOLD, so if it crashes at that point don't worry.)
  203.         ./speed -s 1-20 -r mpn_sqr_basecase mpn_mul_basecase
  204. The technique described above with -CD for showing the time difference in
  205. cycles per limb between two size operations can be done on an NxN
  206. mul_basecase using -E to change the basis for the size increment to N*N.
  207. For instance a 20x20 operation is taken to be doing 400 limbs, and a 16x16
  208. doing 256 limbs.  The following therefore shows the per crossproduct speed
  209. of mul_basecase and sqr_basecase at around 20x20 limbs.
  210.         ./speed -s 16-20 -t 4 -CDE mpn_mul_basecase mpn_sqr_basecase
  211. Of course sqr_basecase isn't really doing NxN crossproducts, but it can be
  212. interesting to compare it to mul_basecase as if it was.  For sqr_basecase
  213. the -F option can be used to base the deltas on N*(N+1)/2 operations, which
  214. is the triangular products sqr_basecase does.  For example,
  215.         ./speed -s 16-20 -t 4 -CDF mpn_sqr_basecase
  216. Both -E and -F are preliminary and might change.  A consistent approach to
  217. using them when claiming certain per crossproduct or per triangularproduct
  218. speeds hasn't really been established, but the increment between speeds in
  219. the range karatsuba will call seems sensible, that being k to k/2.  For
  220. instance, if the karatsuba threshold was 20 for the multiply and 30 for the
  221. square,
  222.         ./speed -s 10-20 -t 10 -CDE mpn_mul_basecase
  223.         ./speed -s 15-30 -t 15 -CDF mpn_sqr_basecase
  224. EXAMPLE COMPARISONS - MALLOC
  225. The gmp manual recommends application programs avoid excessive initializing
  226. and clearing of mpz_t variables (and mpq_t and mpf_t too).  Every new
  227. variable will at a minimum go through an init, a realloc for its first
  228. store, and finally a clear.  Quite how long that takes depends on the C
  229. library.  The following compares an mpz_init/realloc/clear to a 10 limb
  230. mpz_add.  Don't be surprised if the mallocing is quite slow.
  231.         ./speed -s 10 -c mpz_init_realloc_clear mpz_add
  232. On some systems malloc and free are much slower when dynamic linked.  The
  233. speed-dynamic program can be used to see this.  For example the following
  234. measures malloc/free, first static then dynamic.
  235.         ./speed -s 10 -c malloc_free
  236.         ./speed-dynamic -s 10 -c malloc_free
  237. Of course a real world program has big problems if it's doing so many
  238. mallocs and frees that it gets slowed down by a dynamic linked malloc.
  239. EXAMPLE COMPARISONS - STRING CONVERSIONS
  240. mpn_get_str does a binary to string conversion.  The base is specified with
  241. a ".<r>" parameter, or decimal by default.  Power of 2 bases are much faster
  242. than general bases.  The following compares decimal and hex for instance.
  243.         ./speed -s 1-20 -c mpn_get_str mpn_get_str.16
  244. Smaller bases need more divisions to split a given size number, and so are
  245. slower.  The following compares base 3 and base 9.  On small operands 9 will
  246. be nearly twice as fast, though at bigger sizes this reduces since in the
  247. current implementation both divide repeatedly by 3^20 (or 3^40 for 64 bit
  248. limbs) and those divisions come to dominate.
  249.         ./speed -s 1-20 -cr mpn_get_str.3 mpn_get_str.9
  250. mpn_set_str does a string to binary conversion.  The base is specified with
  251. a ".<r>" parameter, or decimal by default.  Power of 2 bases are faster than
  252. general bases on large conversions.
  253. ./speed -s 1-512 -f 2 -c mpn_set_str.8 mpn_set_str.10
  254. mpn_set_str also has some special case code for decimal which is a bit
  255. faster than the general case, basically by giving the compiler a chance to
  256. optimize some multiplications by 10.
  257. ./speed -s 20-40 -c mpn_set_str.9 mpn_set_str.10 mpn_set_str.11
  258. EXAMPLE COMPARISONS - GCDs
  259. mpn_gcd_1 has a threshold for when to reduce using an initial x%y when both
  260. x and y are single limbs.  This isn't tuned currently, but a value can be
  261. established by a measurement like
  262. ./speed -s 10-32 mpn_gcd_1.10
  263. This runs src[0] from 10 to 32 bits, and y fixed at 10 bits.  If the div
  264. threshold is high, say 31 so it's effectively disabled then a 32x10 bit gcd
  265. is done by nibbling away at the 32-bit operands bit-by-bit.  When the
  266. threshold is small, say 1 bit, then an initial x%y is done to reduce it to a
  267. 10x10 bit operation.
  268. The threshold in mpn/generic/gcd_1.c or the various assembler
  269. implementations can be tweaked up or down until there's no more speedups on
  270. interesting combinations of sizes.  Note that this affects only a 1x1 limb
  271. operation and so isn't very important.  (An Nx1 limb operation always does
  272. an initial modular reduction, using mpn_mod_1 or mpn_modexact_1_odd.)
  273. SPEED PROGRAM EXTENSIONS
  274. Potentially lots of things could be made available in the program, but it's
  275. been left at only the things that have actually been wanted and are likely
  276. to be reasonably useful in the future.
  277. Extensions should be fairly easy to make though.  speed-ext.c is an example,
  278. in a style that should suit one-off tests, or new code fragments under
  279. development.
  280. many.pl is a script for generating a new speed program supplemented with
  281. alternate versions of the standard routines.  It can be used for measuring
  282. experimental code, or for comparing different implementations that exist
  283. within a CPU family.
  284. THRESHOLD EXAMINING
  285. The speed program can be used to examine the speeds of different algorithms
  286. to check the tune program has done the right thing.  For example to examine
  287. the karatsuba multiply threshold,
  288. ./speed -s 5-40 mpn_mul_basecase mpn_kara_mul_n
  289. When examining the toom3 threshold, remember it depends on the karatsuba
  290. threshold, so the right karatsuba threshold needs to be compiled into the
  291. library first.  The tune program uses specially recompiled versions of
  292. mpn/mul_n.c etc for this reason, but the speed program simply uses the
  293. normal libgmp.la.
  294. Note further that the various routines may recurse into themselves on sizes
  295. far enough above applicable thresholds.  For example, mpn_kara_mul_n will
  296. recurse into itself on sizes greater than twice the compiled-in
  297. MUL_TOOM22_THRESHOLD.
  298. When doing the above comparison between mul_basecase and kara_mul_n what's
  299. probably of interest is mul_basecase versus a kara_mul_n that does one level
  300. of Karatsuba then calls to mul_basecase, but this only happens on sizes less
  301. than twice the compiled MUL_TOOM22_THRESHOLD.  A larger value for that
  302. setting can be compiled-in to avoid the problem if necessary.  The same
  303. applies to toom3 and DC, though in a trickier fashion.
  304. There are some upper limits on some of the thresholds, arising from arrays
  305. dimensioned according to a threshold (mpn_mul_n), or asm code with certain
  306. sized displacements (some x86 versions of sqr_basecase).  So putting huge
  307. values for the thresholds, even just for testing, may fail.
  308. FUTURE
  309. Make a program to check the time base is working properly, for small and
  310. large measurements.  Make it able to test each available method, including
  311. perhaps the apparent resolution of each.
  312. Make a general mechanism for specifying operand overlap, and a syntax like
  313. maybe "mpn_add_n.dst=src2" to select it.  Some measuring routines do this
  314. sort of thing with the "r" parameter currently.
  315. ----------------
  316. Local variables:
  317. mode: text
  318. fill-column: 76
  319. End: