C语言 比 * 更快的乘法[关闭]

mbzjlibv  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(137)

已关闭,此问题需要details or clarity。它目前不接受回答。
**想改善这个问题吗?**通过editing this post添加详细信息并澄清问题。

上个月关门了。
Improve this question
我正在寻找一种比常规乘法更快的方法。我在vscode中运行代码,据我所知,我没有启用优化。我也尝试了gcc -O 0_. c-o_,但仍然得到相同的结果。我也在M0汇编中写了同样的代码,但常规乘法仍然是最快的。我是否遗漏了什么,也许是时间计算,或者常规乘法真的是最快的方法?

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdint.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. int max(int a, int b) {
  8. return (a > b) ? a : b;
  9. }
  10. uint64_t karatsuba(uint64_t x, uint64_t y) {
  11. if (x < 10 || y < 10) {
  12. return x * y;
  13. }
  14. int n = max(log10(x) + 1, log10(y) + 1) / 2;
  15. uint64_t a = x / (uint64_t)pow(10, n);
  16. uint64_t b = x % (uint64_t)pow(10, n);
  17. uint64_t c = y / (uint64_t)pow(10, n);
  18. uint64_t d = y % (uint64_t)pow(10, n);
  19. uint64_t ac = karatsuba(a, c);
  20. uint64_t bd = karatsuba(b, d);
  21. uint64_t ad_bc = karatsuba(a + b, c + d) - ac - bd;
  22. return ac * (uint64_t)pow(10, 2 * n) + ad_bc * (uint64_t)pow(10, n) + bd;
  23. }
  24. uint64_t multiply(uint64_t x, uint64_t y) {
  25. uint64_t result = 0;
  26. while (x > 0) {
  27. if (x & 1) {
  28. result += y;
  29. }
  30. x >>= 1;
  31. y <<= 1;
  32. }
  33. return result;
  34. }
  35. int main() {
  36. uint64_t i = UINT64_MAX;
  37. uint64_t j = 10;
  38. clock_t t;
  39. clock_t m;
  40. clock_t l;
  41. int n = 9999999;
  42. t = clock();
  43. for (int k = 0; k < n; k++) {
  44. multiply(i, j);
  45. }
  46. t = clock() - t;
  47. double time_taken = ((double)t) / CLOCKS_PER_SEC;
  48. printf("Bit Manipulation Multiplication took %.15f seconds to execute in average\n", time_taken / n);
  49. m = clock();
  50. for (int k = 0; k < n; k++) {
  51. uint64_t k_result = i * j;
  52. }
  53. m = clock() - m;
  54. double time_taken2 = ((double)m) / CLOCKS_PER_SEC;
  55. printf("Regular Multiplication took %.15f seconds to execute in average\n", time_taken2 / n);
  56. l = clock();
  57. for (int k = 0; k < n; k++) {
  58. karatsuba(i, j);
  59. }
  60. l = clock() - l;
  61. double time_taken3 = ((double)l) / CLOCKS_PER_SEC;
  62. printf("Karatsuba Multiplication took %.15f seconds to execute in average\n", time_taken3 / n);
  63. printf("\nResults:\n");
  64. printf("Bit Manipulation Result: %llu\n", multiply(i, j));
  65. printf("Regular Multiplication Result: %llu\n", i * j);
  66. printf("Karatsuba Multiplication Result: %llu\n", karatsuba(i, j));
  67. return 0;
  68. }
kqqjbcuj

kqqjbcuj1#

显然,你的karatsuba算法在这里很差,因为它涉及到多个浮点对数和pow函数。* 每一个,* 最多和整数乘法一样快,所以这显然不是一个改进。
multiply函数中的位移位方法在早期的CPU(如Intel 8086)上曾经更快,其中单个16位x 16位乘法将花费大约150个时钟周期。但是现代CPU已经优化了很多,所以乘法使用的周期要少得多。细节将因CPU类型和使用的确切汇编指令而异,但移位方法最终可能对非常短的整数更快,例如8或16位,但显然不是64位,其中循环开销只是增加了开销。

zc0qhyus

zc0qhyus2#

当你乘64位整数时,普通乘法是最快的。如果不是,我们就不会用它。
老实说,我不明白你为什么要用这些奇怪的方法。你的函数multiply需要跳转,karatsuba需要log10。两者都比处理器中的mul操作慢得多。我强烈推荐阅读和理解汇编和浮点运算是如何工作的。真的很值得

相关问题