如何让我的程序更快?

时间:2014-02-03 22:36:35

标签: c++ performance

今天我正在努力让我的程序更快。该程序扫描100,000个假社会安全号码,名字,姓氏和gpa。我的教授已经开始讨论指针,引用和解除引用,并说使用这些可以通过传递地址来帮助加速程序。我的解释可能很糟糕,因为我并不是真正理解课堂上的主题,所以当你们帮助我的时候,我会在我的书中读到第9章关于价值的呼吁和参考。任何帮助,将不胜感激。感谢!!!

#include<iostream>
#include<fstream>
#include<cstdlib>
#include<ctime>
using namespace std;

struct nameType{
   string ssno;
   string fName;
   string lName;
   double gpa;
};

int load(istream &in,nameType []);

void shellsort(nameType [],int);

void exchange(nameType &, nameType &);

void print(ostream &out,nameType [],int);

int main(void)
{
   ifstream in;
   ofstream out;

   char infile[40],outfile[40];
   nameType name[100000];
   clock_t start, stop;
   double secl=0;
   double secs=0;
   double secp=0;
   double total=0;
   int n;

   cout << "Please enter the input data file name(NO SPACES): ";
   cin >> infile;

   in.open(infile);
   if(in.fail()) {
      cerr<<"problem input file\n"<<endl;
      exit(1);
   }

   cout << "Please enter the output data file name(NO SPACES): ";
   cin >> outfile;

   out.open(outfile);
   if(out.fail()) {
      cerr<<"problem output file\n"<<endl;
      exit(1);
   }

   start = clock();
   n = load(in,name);
   stop = clock();
   secl = (double)(stop - start)/CLOCKS_PER_SEC;
   cout << "Load Time: " << secl << endl;

   start = clock();
   shellsort(name,n);
   stop = clock();
   secs = (double)(stop - start)/CLOCKS_PER_SEC;
   cout << "Sort Time: " << secs << endl;

   start = clock();
   print(out,name,n);
   stop = clock();
   secp = (double)(stop - start)/CLOCKS_PER_SEC;
   cout << "Print Time: " << secp << endl;

   total = secl + secs + secp;
   cout << "Total Time: " << total << endl;

   in.close();
   out.close();

   return 0;
}

int load(istream &in,nameType name[])
{
   int n=0;

   in >> name[n].ssno >> name[n].fName >> name[n].lName >> name[n].gpa;
   while(!in.eof()){
      n++;
      in >> name[n].ssno >> name[n].fName >> name[n].lName >> name[n].gpa;
   }
   return n;
}

void shellsort(nameType name[],int n)
{
   int gap = n/2;
   bool passOk;
   while(gap>0){
      passOk=true;
      for(int i=0; i<n-gap; i++){
         if(name[i].lName>name[i+gap].lName){
            exchange(name[i],name[i+gap]);
            passOk=false;
         }
         else if(name[i].lName == name[i+gap].lName && name[i].fName > name[i+gap].fName){
            exchange(name[i],name[i+gap]);
            passOk=false;
         }
      }
      if(passOk){
         gap/=2;
      }
   }
}

void exchange(nameType &a, nameType &b)
{
   nameType temp;
   temp = a;
   a = b;
   b = temp;
}

void print(ostream &out,nameType name[],int n)
{
   for(int i=0;i<n;i++){
      out << name[i].ssno << " " <<  name[i].fName << " " << name[i].lName << " " << name[i].gpa << endl;
   }
   out << endl;
}

确切的作业细节---我在第5号子弹---

效率 - 时间和空间

编写程序时,时间和空间始终是需要考虑的问题。

在此作业中,您将修改在第一个编程作业中创建的sort_v4.cpp程序。在该赋值中,您需要处理整数数组。让我们用几个项目更新程序:

构建包含社会安全号码,名字,姓氏和GPA的结构。 使用类中描述的间隙概念的新排序技术,它根据姓氏按升序对信息进行排序(如果姓氏相同则需要检查名字)。排序技术称为shell排序。 提高效率 - 时间和空间如下所述。

每个struct元素都包含ID,名字,姓氏和gpa。假设您必须处理100,000名学生。由于两个原因,该计划效率低下

空间问题:如果社会安全号码占用12个字符,则第一个和最后一个占用20个字符,并且作为双倍的gpa占用8个字节,然后结构元素的主要数组消耗(12 + 20 + 20 + 8) )* 100000字节的内存。如果我们加载100,000个名字,这可能没问题。但是,如果我们处理的学生平均数量<50,000,那么就会浪费大量的内存。 时间问题:当你交换两个乱序的元素时,60个字节大约移动3次。在内存中移动总共180个字节。再次,效率低下。

随着结构中成员变量的数量增加,问题变得更糟。

这项任务的重点是

将包含社会安全号码,first,last和gpa的文件读入结构元素数组。处理直到EOF。每行包含有关一名学生的信息。在结构内部,元素可以定义为char []或字符串。如果我们使用char [] vs字符串,你认为它会对性能产生影响吗?做一个预测。 将数组与定时信息一起转储到文件中。 尝试新的排序技术 - 根据两个项目排序结构元素 - 名字和姓氏。 计算每个功能的时间,以查看花费最多时间的位置。 尝试使用指向结构的指针数组来改进内存的使用。 尝试通过交换指针而不是元素来加快交换速度,从而提高效率。

考虑到上面的列表,分配将有三种可能的等级。对于C - 14/20点的最高等级,您必须完成前两个子弹。对于B - 16/20点的最高等级,您必须完成前4个子弹。对于A,您必须完成所有子弹。

我建议通过实现我称之为非指针版本来开始赋值。在main函数上面定义一个结构来保存项目。 main函数应声明struct元素数组。调用加载,排序和打印函数,就像我们在第一个赋值中进行调整一样,以适应结构和新的排序技术,在交换两个元素之前需要考虑两个项目。注意:这次我想查看交换功能。这将为您提供总共4个功能。确保遵循第一个编程任务中规定的指导原则。

对于所有正在尝试A程序的人,请确保在继续之前已经完成并测试了B的基本程序。制作该程序的副本并按如下方式修改程序:

通过在定义中放置*,将struct元素数组更改为指向struct元素的指针数组。 使用new(或malloc),在读入结构成员的值之前,为一个结构元素动态创建空间。 当你交换两个元素时,交换两个指向struct元素的指针而不是struct元素本身。 看一下非指针版本和指针版本的时间。有显着差异吗?

以下是关于计时一个功能的信息。

#include<ctime>
//Create a couple variables of clock_t type.
clock_t  start, stop;
start = clock();
load(x, n);   //call a function to perform a task
stop = clock();
cout << "load time: " << (double)(stop - start)/CLOCKS_PER_SEC << endl;

函数clock()返回自程序启动以来发生的cpu时钟周期数。理想情况下,从上面的代码开始应为0.为了能够了解函数花费多少时间,您必须将经过的时间转换为秒。这是通过获取开始和停止之间的差异,类型转换,然后除以系统定义的CLOCKS_PER_SEC来实现的。在linus公共(或实验室中的外来物品机器)是1,000,000。另请参阅有关该主题的课堂笔记。以下是应该出现在排序数据末尾的示例。

加载时间:0.05 排序时间:2.36 打印时间:0.01 总运行时间:2.42

错失最后期限的罚款,每天1点,最多7天。课程截止日期后7天不接受。

2 个答案:

答案 0 :(得分:0)

如果你看这里:How are arrays passed?

数组已经作为指针传递,你的std :: swap(你称之为“exchange”)的实现已经通过引用传递了。所以这不是你的问题。你的教授有没有抱怨你的程序执行速度?

答案 1 :(得分:0)

在程序中占用大量执行时间的地方称为瓶颈。

常见的瓶颈是文件输入和输出。您可以通过减少或优化瓶颈来加快程序运行速度。

从文件中读取许多小块数据比读取一大块数据需要更多时间。例如,使用一个请求读取10行数据比读取一行数据的10个请求更有效。

访问内存比从文件读取更快,更快。

一般模式是:
1.将大量数据读入内存 2.处理数据 3.根据需要重复1。

因此,您可以将“block”读取命令istream::read用于字节数组中。使用字节数组中的一行数据加载一个字符串并处理该行。从数组重复加载,直到用完为止,然后从文件重新加载。