tune.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* Tune the Karatsuba parameters
  2. *
  3. * Tom St Denis, tomstdenis@gmail.com
  4. */
  5. #include <tommath.h>
  6. #include <time.h>
  7. /* how many times todo each size mult. Depends on your computer. For slow computers
  8. * this can be low like 5 or 10. For fast [re: Athlon] should be 25 - 50 or so
  9. */
  10. #define TIMES (1UL<<14UL)
  11. /* RDTSC from Scott Duplichan */
  12. static ulong64 TIMFUNC (void)
  13. {
  14. #if defined __GNUC__
  15. #if defined(__i386__) || defined(__x86_64__)
  16. unsigned long long a;
  17. __asm__ __volatile__ ("rdtsc\nmovl %%eax,%0\nmovl %%edx,4+%0\n"::"m"(a):"%eax","%edx");
  18. return a;
  19. #else /* gcc-IA64 version */
  20. unsigned long result;
  21. __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
  22. while (__builtin_expect ((int) result == -1, 0))
  23. __asm__ __volatile__("mov %0=ar.itc" : "=r"(result) :: "memory");
  24. return result;
  25. #endif
  26. // Microsoft and Intel Windows compilers
  27. #elif defined _M_IX86
  28. __asm rdtsc
  29. #elif defined _M_AMD64
  30. return __rdtsc ();
  31. #elif defined _M_IA64
  32. #if defined __INTEL_COMPILER
  33. #include <ia64intrin.h>
  34. #endif
  35. return __getReg (3116);
  36. #else
  37. #error need rdtsc function for this build
  38. #endif
  39. }
  40. #ifndef X86_TIMER
  41. /* generic ISO C timer */
  42. ulong64 LBL_T;
  43. void t_start(void) { LBL_T = TIMFUNC(); }
  44. ulong64 t_read(void) { return TIMFUNC() - LBL_T; }
  45. #else
  46. extern void t_start(void);
  47. extern ulong64 t_read(void);
  48. #endif
  49. ulong64 time_mult(int size, int s)
  50. {
  51. unsigned long x;
  52. mp_int a, b, c;
  53. ulong64 t1;
  54. mp_init (&a);
  55. mp_init (&b);
  56. mp_init (&c);
  57. mp_rand (&a, size);
  58. mp_rand (&b, size);
  59. if (s == 1) {
  60. KARATSUBA_MUL_CUTOFF = size;
  61. } else {
  62. KARATSUBA_MUL_CUTOFF = 100000;
  63. }
  64. t_start();
  65. for (x = 0; x < TIMES; x++) {
  66. mp_mul(&a,&b,&c);
  67. }
  68. t1 = t_read();
  69. mp_clear (&a);
  70. mp_clear (&b);
  71. mp_clear (&c);
  72. return t1;
  73. }
  74. ulong64 time_sqr(int size, int s)
  75. {
  76. unsigned long x;
  77. mp_int a, b;
  78. ulong64 t1;
  79. mp_init (&a);
  80. mp_init (&b);
  81. mp_rand (&a, size);
  82. if (s == 1) {
  83. KARATSUBA_SQR_CUTOFF = size;
  84. } else {
  85. KARATSUBA_SQR_CUTOFF = 100000;
  86. }
  87. t_start();
  88. for (x = 0; x < TIMES; x++) {
  89. mp_sqr(&a,&b);
  90. }
  91. t1 = t_read();
  92. mp_clear (&a);
  93. mp_clear (&b);
  94. return t1;
  95. }
  96. int
  97. main (void)
  98. {
  99. ulong64 t1, t2;
  100. int x, y;
  101. for (x = 8; ; x += 2) {
  102. t1 = time_mult(x, 0);
  103. t2 = time_mult(x, 1);
  104. printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
  105. if (t2 < t1) break;
  106. }
  107. y = x;
  108. for (x = 8; ; x += 2) {
  109. t1 = time_sqr(x, 0);
  110. t2 = time_sqr(x, 1);
  111. printf("%d: %9llu %9llu, %9llu\n", x, t1, t2, t2 - t1);
  112. if (t2 < t1) break;
  113. }
  114. printf("KARATSUBA_MUL_CUTOFF = %d\n", y);
  115. printf("KARATSUBA_SQR_CUTOFF = %d\n", x);
  116. return 0;
  117. }
  118. /* $Source: /cvs/libtom/libtommath/etc/tune.c,v $ */
  119. /* $Revision: 1.3 $ */
  120. /* $Date: 2006/03/31 14:18:47 $ */