【问题标题】:multiplication speed for different primitive types不同原始类型的乘法速度
【发布时间】:2018-08-30 22:50:12
【问题描述】:

byte、short、int 和 long 的乘法速度是相同的还是以对数、线性、指数方式增长? 我写了一个小程序来测试它。结果全部返回0;

#include <unistd.h>
#include <chrono>
#include <iostream>

using namespace std;
using namespace std::chrono;

int main()
{
    short a = 0xffea, b = 0xffaa;
    int result, ia = 0xffeaffae, ib = 0xeaffaeff;
    long iresult, la = 0xffeaffaeffdaffad, lb = 0xeaffaeffdaffadff;
    long long lresult;

    auto start = high_resolution_clock::now();
    result = a * b;
    auto end = high_resolution_clock::now();
    auto dur = duration_cast<microseconds>(end - start);

    cout << "short multiplication : " << dur.count() << endl;

    start = high_resolution_clock::now();
    iresult = ia * ib;
    end = high_resolution_clock::now();
    dur = duration_cast<microseconds>(end - start);

    cout << "int multiplication : " << dur.count() << endl;

    start = high_resolution_clock::now();
    lresult = la * lb;
    end = high_resolution_clock::now();
    dur = duration_cast<microseconds>(end - start);

    cout << "long multiplication : " << dur.count() << endl;

    return 0;
 }

我假设 64 位处理器可以以相同的速度计算原始类型;

谢谢

【问题讨论】:

  • PC 中的计时太粗略,无法测量一个算术运算。您需要运行数百万个并且平均。
  • 请不要发布带有行号的代码 - 它会阻止我们编译它。此外,如果您不是专门询问 POSIX 代码,请不要包含 之类的标头。
  • 是的,不同数据类型的乘法时间不同。取决于处理器。对于现代的 32 位处理器,时间应该以 纳秒 为单位。足够小,除非您执行 1E9 操作,否则时间是微不足道的,通常比等待任务切换或 I/O 操作要短得多。
  • @PeteBecker:这就是 C++ 抽象机中逻辑上发生的事情。由于 as-if 规则,添加两个 uint8_t 数字并将结果分配给 uint8_t 可以优化为单字节 add 指令,因为它总是给出与加宽相同的结果,进行更宽的加法,然后只取结果的低字节。当编译器自动向量化您的代码时,这可能非常重要;更窄的类型意味着每个 SIMD 向量有更多的元素。 (如果编译器设法避免像 C 规则所说的那样扩大;有时 gcc 和 clang 做得非常糟糕......)
  • @Pete - 你是一个常见的误解! C++ 提升语义在这里可能不相关,除非您的编译器非常糟糕。编译器通过强制转换、提升、赋值等轻松跟踪底层值的真实大小/范围,并在结果相同的情况下在汇编级别发出更大或更小的操作,因为它适合它们。

标签: c++ performance cpu-architecture


【解决方案1】:

它取决于机器。对于本机数据类型,乘法指令消耗的周期数是相关的。要明确告诉使用的指令,请使用内联汇编或检查汇编输出。对于英特尔处理器,this document 列出了许多指令的 CPU 周期。

rtdsc instruction 以及 cpuid 等其他参数可能会让您大致了解部分代码使用了多少 cpu 周期,但您可能更擅长研究汇编或分析您的应用程序。

但大多数时候,这些都与练习无关。它们大约需要一个周期,即大约 0,000000001 秒。

在大多数情况下,您可以坚持您的假设,并认为乘法对于所有本机数据类型具有相同的成本。

【讨论】:

  • 更重要的是,C++ 源代码中的* 二元运算符并不总是编译为乘法指令。在这种情况下,恒定传播意味着乘法完全优化。 (除非您在禁用优化的情况下编译 OP 的代码,在这种情况下,您正在对堆栈的加载/存储进行基准测试。当然,作为 single 乘法的成本进行准确测量的开销太大;您需要为吞吐量或延迟在循环中执行此操作。)无论如何,使用自动矢量化,short 优于int(SSE4.1 pmullo 很慢),int64_t 需要 AVX512 用于 SIMD mul。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-20
  • 2017-02-07
  • 1970-01-01
  • 2021-05-03
  • 2013-02-02
  • 2021-08-11
  • 1970-01-01
相关资源
最近更新 更多