最佳实践:网络性能的分析与优化
Profier计时网络性能时采用同步推理
测量每一层的运行时间
// profile类,继承自 IProfiler
struct Profiler : public IProfiler
{
typedef std::pair<std::string, float> Record;
std::vector<Record> mProfile;
// 将每一层的运行时间存放到 vector中
virtual void reportLayerTime(const char* layerName, float ms)
{
// find_if找到第一个 r.first 与 layerName 相同的层,返回一个迭代器
auto record = std::find_if(mProfile.begin(), mProfile.end(), [&](const Record& r){ return r.first == layerName; });
// 如果是新的层就push_back进vector
if (record == mProfile.end())
mProfile.push_back(std::make_pair(layerName, ms));
// 如果是vector中已有的层就直接累加时间,因为他是迭代1000次的,肯定会重复,所以要累加时间
else
record->second += ms;
}
// 打印各层的运行时间,打印时要除总的迭代次数
void printLayerTimes()
{
float totalTime = 0;
for (size_t i = 0; i < mProfile.size(); i++)
{
printf("%-40.40s %4.3fms\n", mProfile[i].first.c_str(), mProfile[i].second / TIMING_ITERATIONS);
totalTime += mProfile[i].second;
}
printf("Time over all layers: %4.3f\n", totalTime / TIMING_ITERATIONS);
}
} gProfiler;
//定义迭代次数
static const int TIMING_ITERATIONS = 1000;
// 设置profiler
context->setProfiler(&gProfiler);
// 初始化,将输入缓冲区归零 zero the input buffer ,目的是使用空数据运行推理以计时网络性能
CHECK(cudaMemset(buffers[inputIndex], 0, inputSize));
// Profiling不支持异步方式,只支持同步方式,因此要使用同步执行函数 execute()
// 执行过程中,每一层都会调用 profiler 回调函数,存储执行时间
for (int i = 0; i < TIMING_ITERATIONS;i++)
context->execute(batchSize, buffers);
// 打印各层的运行时间
gProfiler.printLayerTimes();