C++ 数据访问基准

标签 c++ benchmarking

正在用 C++ 编写简单的基准测试来比较不同平台上数据访问的执行时间。我得到了奇怪的结果。我测量顺序顺序访问和间接顺序访问的时间。为此,我只是以两种不同的方式将一个数组数据复制到另一个数组数据。代码和结果如下。 我得到的时间是模棱两可的。对 int 数据类型的评估表明,顺序访问速度更快(没问题)。但对于 float 和 double 类型来说恰恰相反(见下面的时间结果)。也许我做的基准测试是错误的,或者有一些我没有考虑到的陷阱?或者您能否推荐一些基准工具来比较不同数据类型的数据访问或简单操作性能?

template<typename T>
std::chrono::nanoseconds::rep PerformanceMeter<T>::testDataAccessArr()
{
    std::chrono::nanoseconds::rep totalSequential = 0;

    T* arrDataIn = new T[k_SIZE];
    T* arrDataOut = new T[k_SIZE];

    std::generate_n(arrDataIn, k_SIZE, DataProcess<T>::valueGenerator);
    DataProcess<T>::clearCache();

    std::chrono::nanoseconds::rep timeSequential = measure::ns(copySequentialArr, arrDataIn, arrDataOut, k_SIZE);

    std::cout << "Sequential order access:\t" << timePrint(timeSequential) << "\t";
    std::cout.flush();

    std::chrono::nanoseconds::rep totalIndirection = 0;
    T** pointers = new T*[k_SIZE];
    T** pointersOut = new T*[k_SIZE];
    for (size_t i = 0; i < k_SIZE; ++i)
    {
        pointers[i] = &arrDataIn[i];
        pointersOut[i] = &arrDataOut[i];
    }

    std::generate_n(arrDataIn, k_SIZE, DataProcess<T>::valueGenerator);
    std::generate_n(arrDataOut, k_SIZE, DataProcess<T>::valueGenerator);

    DataProcess<T>::clearCache();

    totalIndirection = measure::ns(copyIndirectionArr, pointers, pointersOut, k_SIZE);

    std::cout << std::endl << "Indirection order access:\t" << timePrint(totalIndirection) << std::endl;
    std::cout.flush();

    delete[] arrDataIn;
    delete[] arrDataOut;
    delete[] pointers;
    delete[] pointersOut;

    return timeSequential;
}

template <typename T>
void PerformanceMeter<T>::copySequentialArr(const T* dataIn, T* dataOut, size_t dataSize)
{
    for (int i = 0; i < dataSize; i++)
        dataOut[i] = dataIn[i];
}

template <typename T>
void PerformanceMeter<T>::copyIndirectionArr(T** dataIn, T** dataOut, size_t dataSize)
{
    for (int i = 0; i < dataSize; i++)
        *dataOut[i] = *dataIn[i];
}

结果:

--------------------测量整数----------------

数据:10MB;迭代次数:1

顺序访问:8.50454ms

间接顺序访问:11.6925ms

--------------------测量 float ------------

数据:10MB;迭代次数:1

顺序访问:8.84023ms

间接顺序访问:8.53148ms

--------------------测量双------------

数据:10MB;迭代次数:1

顺序访问:5.57747ms

间接顺序访问:3.72843ms

最佳答案

以下是 GCC 6.3 使用 -O2 的汇编输出示例(使用 T = int): copySequentialArrcopyIndirectionArr .

从程序集可以明显看出它们非常相似,但是 copyIndi​​rectionArrcopySequentialArr 需要两条 mov 指令。由此我们可以得出一些结论,copySequentialArr 是最快的。

使用 T = double 时也是如此:copySequentialArrcopyIndirectionArr .

矢量化

当我们开始使用 -O3 时变得很有趣:copySequentialArrcopyIndirectionArr . copyIndi​​rectionArr 没有变化,但 copySequentialArr 现在由编译器矢量化。在正常情况下,这种矢量化将使它比以前更快。

免责声明

这些对生成的汇编代码的检查是“脱离上下文”的,因为如果编译器知道上下文,它会进一步优化它。

关于C++ 数据访问基准,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44068981/

相关文章:

c++ - 在类中初始化时 C++ 中奇怪且不正确的数组大小行为

c++ - 判断函数参数是否为函数

c++ - 套接字通过并发FTP传输接收到错误的数据

c++ - C++中具有负索引的类数组数据结构

redis - 如何降低 epoll_wait 调用的 finish_task_switch() 的 CPU 使用率?

python - 基准测试 : does python have a faster way of walking a network folder?

c++ - const char* 没有传递完整的文件名

unix - 'real' 、 'user' 和 'sys' 在 time(1) 的输出中是什么意思?

performance - 内存基准图 : understanding cache behaviour

linq-to-sql - 基准 Linq2SQL、Subsonic 2、Subsonic 3 - 还有其他让它们更快的想法吗?