64,670
社区成员
在 C++ 算法中使用 MKL 函数库并进行加速后,跑10轮大约需要 280 毫秒,但将其提取出来并转化为 dll 库后,跑10轮就达到了 500 毫秒。
我的CPP代码:
auto starttime = system_clock::now();
cleanData = ssveP.getWarmFilter(newData);
std::vector<std::vector<double>> eps;
std::vector<std::vector<double>> pred;
vector<vector<vector<vector<double>>>> corr;
vector<vector<vector<double>>>filterData;
ssveP.testPhaseOnlineADA(res, pred, eps, corr, ssveP, filterData, cleanData, M, method, T, 0);
duration<double> diff = system_clock::now() - starttime;
std::cout << endl << "所耗时间为:" << diff.count() << "s";
我的DLL代码:
__declspec(dllexport) Result testPhaseOnlineADA(std::vector<std::vector<double>> newData)
{
//double* result = new double[2];
Result result;
std::vector<std::vector<double>> epsilons;
std::vector<std::vector<double>> predLabels;
vector<vector<vector<vector<double>>>> corrCoef;
vector<vector<vector<double>>>filterData;
int res = -1;
string method = "DW11";
double T = -0.005;
int C = 0;
vector<vector<vector<double>>>cleanData;
cleanData = DWT.getWarmFilter(newData);
DWT.testPhaseOnlineADA(res, predLabels, epsilons, corrCoef, DWT, filterData, cleanData, M, method, T, C);
//std::cout << "epsilons[0][0]:" << epsilons[0][0] << std::endl;
double epsMin;
epsMin = epsilons[0][0];
int wIdx = 0;
for (int m = 0; m < epsilons.size(); m++)
{
if (epsMin > epsilons[m][0])
{
epsMin = epsilons[m][0];
wIdx = m;
}
}
if (epsMin < T)
{
res = predLabels[wIdx][0] + 1;
}
/* result[0] = res;
result[1] = wIdx;*/
result.res = res;
result.wIdx;
result.cleanData = cleanData;
return result;
}
调用代码:
//DWORD start_time = GetTickCount64();
auto starttime = system_clock::now();
Result result = testPhaseOnlineADA(newData);
duration<double> diff = system_clock::now() - starttime;
std::cout << "testPhaseOnlineADA所耗时间为:" << diff.count() << "s" << std::endl;
1. 尝试过使用 "const "数据来减少内存,并尽量缩短计算时间。
2. 把数据全部放在 DLL 中,这样可以减少数据传输的损失。
希望 DLL 也能像cpp 代码一样运行,并且 10 轮计算能在 400 毫秒内完成。
我还想知道如果在 Unity/Android 中使用这个 DLL,速度是否会变慢,因为我使用了 Visual Studio 的加速功能。
我找到的一些资料和尝试:
1. 考虑了 DLL 的一些加载特性尝试连续加载了好几次,但计算出的时间并没有减少。我在主函数的开头调用了 DLL,而不是在 while 循环中,应该没有重复加载的问题。只是计算的数据很大,需要将它们切割成 50*140 个部分,每个部分有三个维度......
2. 使用了 "const vector<vector<vector>>& newData"。仍然超时过400ms。还有一个很奇怪的情况,我在 getWarmFilter() 中使用了 "const vector<vector<vector>>& newData",结果超过原来 30ms......使程序比以前慢了很多。
做过的一些测试信息:
1. 猜测可能是内部使用了矩阵运算库 MKL 使 DLL 比以前慢了,但我注释掉了 MKL 代码。运行速度慢了 1 毫秒,所以确定这不是 MKL 计算的问题。
2. 分别计算了 getWarmFilter() 和 testPhaseADA(),发现 cpp 中的 testPhaseADA 只需要约 40 毫秒,如果变成 DLL 并在 cpp 中调用,则需要约 70 毫秒。算法只计算 10 轮,每轮多耗时 30ms。10 轮之后,时间超过 400ms,甚至达到 500ms。
3. 在 testPhaseADA() 中加入了一个计时器,发现 DLL 中的这个函数仍然需要 70 毫秒...是不是我打包 DLL 的方式出了问题,导致它的运行速度不如 cpp 程序那么快?我使用了 "C/C++->优化->优化->最大优化(速度优先) (/O2)" 和 "C/C++->优化->大小时间优化->速度优先 (/Ot)"。这是否会改变程序的速度,但不会影响 DLL?因为我重置了这个设置,并创建了一个新的 DLL,速度变得很慢,每轮耗时 100 毫秒,所以它在编译 DLL 时是有用的。但在编译 DLL 后,速度就没有直接在 cpp 程序中写那么快了。
你可以首先把main函数的内容直接放到dll里面去,这样完全在dll里面运行,看看有没有差异,可以多循环几次把时间拉长到数秒钟,这样更直观。
编译选项的问题?
使用电脑计时有时误差会很大,因为待测程序段的运行会影响电脑时钟。
将待测程序段循环足够多次,手动掐秒表计时可能更准确。