C++ 模板复杂图像读取类执行时间慢,声明和实现分离
C++ Slow execution time of template complex image reading class, with separated declaration and implementation
我正在尝试制作读取复杂图像的二进制文件。我使用VisualStudio 2010。这是代码1:
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <math.h>
#include <stdlib.h>
#define NX 21843
#define NY 22380
#include <windows.h>
class CTimer
{
public:
CTimer()
{
QueryPerformanceFrequency(&mqFreq);
}
~CTimer() {}
void Start()
{
QueryPerformanceCounter(&mqStart);
}
void End()
{
QueryPerformanceCounter(&mqEnd);
}
double GetTimeInSeconds()
{
return (mqEnd.QuadPart - mqStart.QuadPart)/static_cast<double>(mqFreq.QuadPart);
}
private:
LARGE_INTEGER mqStart;
LARGE_INTEGER mqEnd;
LARGE_INTEGER mqFreq;
};
using namespace std;
int main(void)
{
CTimer Time;
Time.Start();
ifstream INFILE;
INFILE.open("e:\WORK\CIMG.bindat", ios::binary);
short ***im_ptr;
im_ptr = new short** [2];
for (int i=0; i<2; i++){
im_ptr[i] = new short* [NX];
for (int j=0; j<NX; j++){
im_ptr[i][j] = new short [NY];
}
}
for(int i=0; i<2; i++){
for (int j=0; j<NX; j++){
for (int k=0; k<NY; k++){
int index = i*NY*NX + j*NY + k;
INFILE.read((char*)&im_ptr[i][j][k], sizeof(short));
if (index == 2*NX*NY-1){
INFILE.close();}
}
}
}
for (int i=0; i<2; i++){
for (int j=0; j<NX; j++){
delete[] im_ptr[i][j];
}
delete[] im_ptr[i];
}
delete[] im_ptr;
Time.End();
std::cout << Time.GetTimeInSeconds() << " seconds" << std::endl;
std::cout << "nPress any key to exit" << std::endl;
getch();
return 0;
}
此代码工作正常,但仅适用于 SHORT 类型的图像。
我决定做模板类,它允许读取许多不同数据类型的图像,并将声明和实现分开。这是代码2:
stdafx.h 的 - 声明我的班级
#pragma once
#include "targetver.h"
#include <stdio.h>
#include <tchar.h>
template<typename DataType>
class SARDataLoader
{
private:
int day,month,year;
public:
DataType*** LoadComplexImage(int, int);
int DeleteImageFromMemory(DataType***, int);
};
SARDataLoader_C.cpp - 实现我的类
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <stdlib.h>
using namespace std;
template<typename DataType>
DataType*** SARDataLoader<DataType>::LoadComplexImage(int NX, int NY){
using namespace std;
ifstream INFILE;
INFILE.open(""e:\WORK\CIMG.bindat"", ios::binary);
DataType ***im_ptr;
im_ptr = new DataType** [2];
for (int i=0; i<2; i++){
im_ptr[i] = new DataType* [NX];
for (int j=0; j<NX; j++){
im_ptr[i][j] = new DataType [NY];
}
}
for(int i=0; i<2; i++){
for (int j=0; j<NX; j++){
for (int k=0; k<NY; k++){
int index = i*NY*NX + j*NY + k;
INFILE.read((char*)&im_ptr[i][j][k], sizeof(DataType));
if (index == 2*NX*NY-1){
INFILE.close();}
}
}
}
return im_ptr;
};
template<typename DataType> int SARDataLoader<DataType>::DeleteImageFromMemory(DataType*** im_ptr, int NX){
for (int i=0; i<2; i++){
for (int j=0; j<NX; j++){
delete[] im_ptr[i][j];
}
delete[] im_ptr[i];
}
delete[] im_ptr;
return 112345;
};
template class SARDataLoader<short>;//explicit instantiation short
主.cpp - 使用我的类
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <fstream>
#include <math.h>
#define NX 21843
#define NY 22380
#include <windows.h>
class CTimer
{
public:
CTimer()
{
QueryPerformanceFrequency(&mqFreq);
}
~CTimer() {}
void Start()
{
QueryPerformanceCounter(&mqStart);
}
void End()
{
QueryPerformanceCounter(&mqEnd);
}
double GetTimeInSeconds()
{
return (mqEnd.QuadPart - mqStart.QuadPart)/static_cast<double>(mqFreq.QuadPart);
}
private:
LARGE_INTEGER mqStart;
LARGE_INTEGER mqEnd;
LARGE_INTEGER mqFreq;
};
using namespace std;
int main(void)
{
CTimer Time;
Time.Start();
std::cout <<"nIMAGE1 Loading..."<< std::endl;
SARDataLoader<short> IMG_LOADER;
short ***im_ptr = IMG_LOADER.LoadComplexImage(NX, NY);
int CODE = IMG_LOADER.DeleteImageFromMemory(im_ptr, NX);
Time.End();
double run_time = Time.GetTimeInSeconds();
std::cout <<CODE<<"nRUNTIME "<<run_time<<" seconds"<<"n...Press any key to exit...n"<<std::endl;
getch();
return 0;
}
此代码有效,并且执行与 code1 相同的操作。我使用 CTimer 类进行代码 1 和代码 2 执行时间测量。它说 code2 的执行时间几乎是 code1 的三倍。谁能告诉我是什么原因造成的以及如何解决这个问题?
查看两个示例(非优化编译)生成的汇编代码,我注意到只有两个差异:
-
处理
NX
和NY
值需要在模板化版本中进行实际计算,因为它们作为参数传递,而原始代码是硬编码常量(通过#define
秒)。然而,添加到模板化代码中的工作量看起来微不足道 - 我无法想象它们会导致执行时间的可衡量差异。 -
模板化代码在从
LoadComplexImage()
返回时调用ifstream INFILE
的析构函数 - 此操作的执行时间包含在模板化版本的计时器中。 由于INFILE
的 dtor 在原始代码中返回之前不会调用main()
因此它不包含在该示例的计时中。
我可以相信ifstream
的 dtor 可能需要可测量的时间(调试库中的 dtor 可能很慢)。 由于我不知道这些运行的时间是什么,我不知道它是否会增加 200%。但在我看来,如果不是全部的话,它可能是至少很大一部分增长的罪魁祸首。
要比较同类产品,您需要重新调整原始测试以包括INFILE
的销毁,或者在这两种情况下将输入文件的打开移动到定时代码之外,并将其作为参考传递到模板化版本中(或使用全局进行测试)。 将输入文件的打开和关闭保持在定时区域之外似乎是对此内容进行基准测试的更好选择。
- .cpp和.h文件中的模板专用化声明
- 未在作用域中声明unordered_map
- C++避免重复声明的语法是什么
- 如何确保C++函数在定义之前声明(如override关键字)
- 错误:未在此范围内声明'reverse'
- 奇怪的(对我来说)返回声明 - 在谷歌上找不到任何关于它的信息
- 为什么在定义函数之前先声明它
- 如何声明特征矩阵,然后通过嵌套循环初始化它
- 如何用默认模板参数分离模板类的声明和实现
- 不为模板化类分离函数声明和定义是一种好的做法吗
- 如何将显式声明的构造函数分离到 .h 和 .cpp 文件中?
- 在C++中分离声明和初始化
- 在C++11中分离枚举声明和定义
- 可以分离内联函数的声明和定义
- C++ 模板复杂图像读取类执行时间慢,声明和实现分离
- C++模板的声明和定义分离
- C++生成文件,同时分离声明和实现
- 如何在分离声明和定义时为友元函数提供默认参数
- 如何在类分离之外声明泛型类的友元
- 在模板化嵌套类中分离运算符重载<<的声明和定义的正确语法?