C++中ipp库和标准库效率对比
·
以前一直在使用ipp库,但是ipp库仅针对Intel的处理器,最近需要将服务器从Intel的CPU替换到华为鲲鹏,IPP的加速库便不不能再使用了。所以在考虑使用鲲鹏的KML库替换还是直接用标准库替换,萌生了对比IPP可和标准库效率的想法。对比代码如下:
#include <QCoreApplication>
#include <QElapsedTimer>
#include <iostream>
#include "./Include/ipp/ipp.h"
#include <cstring> // 标准库函数
#include <random>
#include <algorithm>
#include <iterator>
// Windows环境需要显式链接IPP库
#pragma comment(lib, "ippsmt.lib")
#pragma comment(lib, "ippcoremt.lib")
constexpr int SIZE = 1 << 20; // 1MB数据(262,144个float)
constexpr int TRIALS = 1000; // 测试次数
// 测试IPP函数
void testIPP() {
Ipp32f* src = nullptr, * dst = nullptr;
QElapsedTimer timer;
// 内存分配
timer.start();
for (int i = 0; i < TRIALS; ++i) {
src = ippsMalloc_32f(SIZE);
ippsFree(src);
}
auto mallocTime = timer.nsecsElapsed() / TRIALS;
// 内存赋值
src = ippsMalloc_32f(SIZE);
timer.start();
for (int i = 0; i < TRIALS; ++i) {
ippsSet_32f(3.14159f, src, SIZE);
}
auto setTime = timer.nsecsElapsed() / TRIALS;
ippsFree(src);
// 内存置零
src = ippsMalloc_32f(SIZE);
timer.start();
for (int i = 0; i < TRIALS; ++i) {
ippsZero_32f(src, SIZE);
}
auto zeroTime = timer.nsecsElapsed() / TRIALS;
ippsFree(src);
// 内存拷贝
src = ippsMalloc_32f(SIZE);
dst = ippsMalloc_32f(SIZE);
ippsSet_32f(2.71828f, src, SIZE);
timer.start();
for (int i = 0; i < TRIALS; ++i) {
ippsCopy_32f(src, dst, SIZE);
}
auto copyTime = timer.nsecsElapsed() / TRIALS;
ippsFree(src);
ippsFree(dst);
std::cout << "[IPP] Malloc: " << mallocTime << " ns\n"
<< "[IPP] Set: " << setTime << " ns\n"
<< "[IPP] Zero: " << zeroTime << " ns\n"
<< "[IPP] Copy: " << copyTime << " ns\n";
}
// 测试标准库
void testSTD() {
float* src = nullptr, * dst = nullptr;
QElapsedTimer timer;
// 内存分配
timer.start();
for (int i = 0; i < TRIALS; ++i) {
src = new float[SIZE];
delete[] src;
}
auto mallocTime = timer.nsecsElapsed() / TRIALS;
// 内存赋值(循环)
src = new float[SIZE];
timer.start();
for (int i = 0; i < TRIALS; ++i) {
#pragma omp simd for
for (int i = 0; i < SIZE; ++i)
src[i] = 3.14159f;
//std::fill_n(src, SIZE, 3.14159f);
}
auto setTime = timer.nsecsElapsed() / TRIALS;
delete[] src;
// 内存置零(memset)
src = new float[SIZE];
timer.start();
for (int i = 0; i < TRIALS; ++i) {
memset(src, 0, SIZE * sizeof(float));
}
auto zeroTime = timer.nsecsElapsed() / TRIALS;
delete[] src;
// 内存拷贝(memcpy)
src = new float[SIZE];
dst = new float[SIZE];
memset(src, 0, SIZE * sizeof(float));
timer.start();
for (int i = 0; i < TRIALS; ++i) {
memcpy(dst, src, SIZE * sizeof(float));
}
auto copyTime = timer.nsecsElapsed() / TRIALS;
delete[] src;
delete[] dst;
std::cout << "[STD] Malloc: " << mallocTime << " ns\n"
<< "[STD] Set: " << setTime << " ns\n"
<< "[STD] Zero: " << zeroTime << " ns\n"
<< "[STD] Copy: " << copyTime << " ns\n";
}
// 生成随机浮点数组
void generateRandomData(float* data, size_t size) {
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<float> dist(0.0f, 1000.0f);
for (size_t i = 0; i < size; ++i) {
data[i] = dist(gen);
}
}
// 标准库计算均值与标准差
void stdMeanStdDev(const float* data, size_t size, float& mean, float& stdDev) {
double sum = 0.0, sumSq = 0.0;
for (size_t i = 0; i < size; ++i) {
sum += data[i];
sumSq += data[i] * data[i];
}
mean = sum / size;
stdDev = std::sqrt((sumSq - sum * sum / size) / (size - 1)); // 样本标准差
}
// 性能测试主函数
void performanceTest(size_t dataSize, int iterations) {
// 内存分配与数据初始化
Ipp32f* ippData = ippsMalloc_32f(dataSize);
std::vector<float> stdData(dataSize);
generateRandomData(ippData, dataSize);
std::copy(ippData, ippData + dataSize, stdData.begin());
// 预热缓存(可选)
std::sort(stdData.begin(), stdData.end());
// 测试排序性能
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
ippsSortAscend_32f_I(ippData, dataSize); // IPP原地排序
}
auto ippSortTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start
).count();
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
std::sort(stdData.begin(), stdData.end()); // 标准库排序
}
auto stdSortTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start
).count();
// 测试均值与标准差计算性能
float ippMean, ippStdDev;
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
ippsMeanStdDev_32f(ippData, dataSize, &ippMean, &ippStdDev, ippAlgHintFast); // IPP计算
}
auto ippStatTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start
).count();
float stdMean, stdStdDev;
start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < iterations; ++i) {
stdMeanStdDev(stdData.data(), dataSize, stdMean, stdStdDev); // 标准库计算
}
auto stdStatTime = std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::high_resolution_clock::now() - start
).count();
// 输出结果
std::cout << "===== 性能对比 (数据量: " << dataSize << ", 迭代次数: " << iterations << ") =====\n";
std::cout << "排序:\n"
<< " IPP ippsSortAscend_32f_I: " << ippSortTime << " ms\n"
<< " std::sort: " << stdSortTime << " ms\n";
std::cout << "统计计算:\n"
<< " IPP ippsMeanStdDev_32f: " << ippStatTime << " ms\n"
<< " 标准库实现: " << stdStatTime << " ms\n";
ippsFree(ippData);
}
int main(int argc, char* argv[])
{
QCoreApplication a(argc, argv);
std::cout << "=== Intel IPP Performance ===\n";
testIPP();
std::cout << "\n=== Standard Library Performance ===\n";
testSTD();
performanceTest(1e6, 10); // 测试100万数据,迭代10次
return 0;
}
使用1000次对1MB数据(262,144个float)的效率对比。对比结果如下:
Windows系统Debug模式
=== Intel IPP Performance ===
[IPP] Malloc: 1293522 ns
[IPP] Set: 174418 ns
[IPP] Zero: 94937 ns
[IPP] Copy: 501033 ns
=== Standard Library Performance ===
[STD] Malloc: 1202868 ns
[STD] Set: 1940080 ns
[STD] Zero: 93922 ns
[STD] Copy: 190766 ns
===== 性能对比 (数据量: 1000000, 迭代次数: 10) =====
排序:
IPP ippsSortAscend_32f_I: 240 ms
std::sort: 1404 ms
统计计算:
IPP ippsMeanStdDev_32f: 2 ms
标准库实现: 26 ms
F:\Workspace\Code\Qt\TestIntelIpps\x64\Debug\TestIntelIpps.exe (进程 21008)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
Windows系统Release模式
=== Intel IPP Performance ===
[IPP] Malloc: 48886 ns
[IPP] Set: 301834 ns
[IPP] Zero: 87169 ns
[IPP] Copy: 544983 ns
=== Standard Library Performance ===
[STD] Malloc: 44820 ns
[STD] Set: 710 ns
[STD] Zero: 85777 ns
[STD] Copy: 211307 ns
===== 性能对比 (数据量: 1000000, 迭代次数: 10) =====
排序:
IPP ippsSortAscend_32f_I: 229 ms
std::sort: 109 ms
统计计算:
IPP ippsMeanStdDev_32f: 3 ms
标准库实现: 0 ms
F:\Workspace\Code\Qt\TestIntelIpps\x64\Release\TestIntelIpps.exe (进程 26764)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
Linux系统(Centos 7.9) Debug模式
=== Intel IPP Performance ===
[IPP] Malloc: 350 ns
[IPP] Set: 206298 ns
[IPP] Zero: 104632 ns
[IPP] Copy: 766895 ns
=== Standard Library Performance ===
[STD] Malloc: 145 ns
[STD] Set: 2213560 ns
[STD] Zero: 143366 ns
[STD] Copy: 837936 ns
===== 性能对比 (数据量: 1000000, 迭代次数: 10) =====
排序:
IPP ippsSortAscend_32f_I: 300 ms
std::sort: 1437 ms
统计计算:
IPP ippsMeanStdDev_32f: 3 ms
标准库实现: 31 ms
按 <RETURN> 来关闭窗口...
Linux系统(Centos 7.9) Release模式
=== Intel IPP Performance ===
[IPP] Malloc: 214 ns
[IPP] Set: 230157 ns
[IPP] Zero: 88688 ns
[IPP] Copy: 509544 ns
=== Standard Library Performance ===
[STD] Malloc: 42 ns
[STD] Set: 725504 ns
[STD] Zero: 274262 ns
[STD] Copy: 614060 ns
===== 性能对比 (数据量: 1000000, 迭代次数: 10) =====
排序:
IPP ippsSortAscend_32f_I: 231 ms
std::sort: 109 ms
统计计算:
IPP ippsMeanStdDev_32f: 3 ms
标准库实现: 12 ms
按 <RETURN> 来关闭窗口...
本机系统为Windows 11 专业版 24H2 CPU类型为Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz 3.60 GHz。
综合对比下来,除Set外、其余函数标准库优化相当不错。接近与IPP库的性能。而SET函数IPP库有10倍以上的速度提升。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐


所有评论(0)