C++写的算法编译成dll后计算速度变慢了

Momo__zz 2024-04-11 16:49:46

在 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 程序中写那么快了。

 

 

 

...全文
93 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复

你可以首先把main函数的内容直接放到dll里面去,这样完全在dll里面运行,看看有没有差异,可以多循环几次把时间拉长到数秒钟,这样更直观。

  • 打赏
  • 举报
回复

编译选项的问题?

Momo__zz 04-13
  • 举报
回复
@日立奔腾浪潮微软松下联想 现在所有编译都是Release的选项,应该不是这个的问题……
赵4老师 04-12
  • 打赏
  • 举报
回复

使用电脑计时有时误差会很大,因为待测程序段的运行会影响电脑时钟。
将待测程序段循环足够多次,手动掐秒表计时可能更准确。

Momo__zz 04-13
  • 举报
回复
@赵4老师 毫秒级的话手动掐秒表可能没有电脑计时来的精准。我的算法循环次数只要求10~25次,单次要在400ms内。
赵4老师 04-15
  • 举报
回复
@Momo__zz 你循环执行比如一百万次,掐秒表计时就算误差±1秒,除一百万,那也是±1微妙
Ben 。 04-11
  • 打赏
  • 举报
回复

这应该不是因为封装成DLL的问题,有可能是C++编译VS运行时,有开启多线程或用到MKL等优化的库。但封装成DLL后,这些优化的库不是和该DLL一个目录下,所以没有用到优化加速。就是C++源码运行时有优化加速,DLL运行时没有优化加速。

Momo__zz 04-13
  • 举报
回复
@Ben 。 我现在是都放在同一个dll目录下的,而且实际上我注释了MKL之后程序只加速了1~3ms,我封装成dll之后平均每轮都增加了30+ms。
ztenv 版主 04-11
  • 打赏
  • 举报
回复

newData这个有多大?

Momo__zz 04-13
  • 举报
回复
@ztenv 这个是随着计算次数递增的,第一次是50*8,第二次是100*8,然后他们做了warmFilter之后变成了三维矩阵,也是越来越大的。但是最后是会转换成一个1250*8*40*50的四维,是放在dll中计算的,之前写的时候没有把它们换成1维矩阵,但是直接调用时间也在要求范围内,所以就直接四维计算了……

64,670

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧