C++ 模板复杂图像读取类执行时间慢,声明和实现分离

标签 c++ visual-studio-2010 templates stl execution-time

我正在尝试制作复杂图像读取的二进制文件。我使用 VisualStudio 2010。这里是 code1:

      #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 类型的图像。

我决定做模板类,它允许读取许多不同数据类型的图像,并将声明和实现分开。这是code2:

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

MAIN.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 类来测量 code1code2 执行时间。 它说 code2 执行时间几乎比 code1 慢三倍。 谁能告诉我是什么原因造成的以及如何解决这个问题?

最佳答案

查看两个示例(非优化编译)生成的汇编代码,我注意到只有两个不同之处:

  1. 处理 NXNY 值需要在模板版本中进行实际计算,因为它们作为参数传递,而原始代码是硬编码的常量(通过 #defines)。然而,添加到模板代码中的工作量看起来微不足道 - 我无法想象它们会导致执行时间出现可衡量的差异。

  2. 模板化代码在从 LoadComplexImage() 返回时调用 ifstream INFILE 的析构函数 - 此操作的执行时间包含在模板化版本。由于 INFILE 的 dtor 在 main() 返回原始代码之前不会被调用,因此它不包括在该示例的计时中。

    <

我相信 ifstream 的 dtor 可能需要大量时间(调试库中的 dtor 可能非常慢)。因为我不知道这些运行的时间是什么,所以我不知道它是否会导致 200% 的增长。但在我看来,即使不是全部,它也可能是至少很大一部分增长的罪魁祸首。

要进行同类比较,您需要重新调整原始测试以包括 INFILE 的销毁,或者将输入文件的打开移动到两者中的定时代码之外案例,并将其作为引用传递到模板化版本中(或使用全局变量进行测试)。将输入文件的打开和关闭保持在计时区域之外似乎是对这些东西进行基准测试的更好选择。

关于C++ 模板复杂图像读取类执行时间慢,声明和实现分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20017110/

相关文章:

c++ - stringstream 输出的原因是什么?

c++ - 在C++中初始化参数化类型的数组

c++ - 如何在成员模板函数中为不同类型选择代码路径

visual-studio-2010 - 标记一个区域不受自动格式化规则的影响

c++ - C++模板泛型(模板参数列表)

c++ - 如何编写一个模板类而不是多个模板类?

c++ - 模板的另一个问题

php - 使用 PHP 编写脚本的游戏引擎?

c# - 申请路径

visual-studio-2010 - 依赖 Walker 错误 : The Side-by-Side configuration information for "ABC.DLL" contains errors