【问题标题】:How can I make my program faster? [closed]如何让我的程序更快? [关闭]
【发布时间】:2014-02-27 15:26:06
【问题描述】:

今天我正在努力使我的程序更快。该程序扫描了 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 排序。 提高效率 - 时间和空间如下所述。

每个结构元素都包含一个 ID、名字、姓氏和 gpa。假设您必须处理 100,000 名学生。该程序效率低下有两个原因

空格问题:如果社保号占12个字符,第一个和最后一个各占20个字符,gpa作为double占8个字节,那么结构元素的主数组消耗(12+20+20+8 )*100000 字节的内存。如果我们加载 100,000 个名称,这可能没问题。但是如果我们处理的平均学生数量

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

本次作业的重点是

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

考虑到上述列表,作业将有三个可能的成绩。要获得 C - 14/20 分的最高成绩,您必须完成前两个项目符号。对于 B - 16/20 分的最高等级,您必须完成前 4 个项目符号。对于 A,您必须完成所有项目符号。

我建议通过实现我所说的非指针版本来开始分配。在 main 函数上方定义一个结构来保存项目。主函数应该声明结构元素的数组。调用 load、sort 和 print 函数,就像我们在第一个分配中所做的那样,进行调整以适应结构和新的排序技术,其中在交换两个元素之前需要考虑两个项目。注意:这次我想看看交换功能。这将为您提供总共 4 个功能。确保遵循第一个编程作业中所述的准则。

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

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

以下是有关计时一项功能的信息。

#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时钟周期数。理想情况下,上述代码中的 start 应该是 0。为了能够了解一个函数需要多少时间,您必须将经过的时间转换为秒。这是通过获取开始和停止之间的差异、类型转换,然后除以系统定义的 CLOCKS_PER_SEC 来实现的。在 linus public(或实验室中的外星机器)上是 1,000,000。另请参阅有关该主题的课堂笔记。以下是排序数据末尾应显示的示例。

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

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

【问题讨论】:

  • 没有人会挥动魔杖让你的程序更快。根据输入文件的结构,shellsort 可能不是最佳的。使用分析器查看每行代码的执行时间。

标签: c++ performance


【解决方案1】:

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

数组已经作为指针传递,并且您的 std::swap 实现(您称为“交换”)已经通过引用传递。所以在你的情况下这不是问题。你的教授抱怨过你的程序执行速度吗?

【讨论】:

  • 让我粘贴给我们的确切任务。也许这有助于我的解释。
  • 好的,在这种情况下,作业说:“尝试通过使用指向结构的指针数组来提高内存的使用。尝试通过交换指针来加快交换速度来提高效率而不是元素。”如果你看看你的算法,现在它正在使用实际的结构。您想将其更改为 void shellsort(nameType* name[],int n) 指向 nameTypes 的指针数组,而不是 nameTypes 数组。同样,您需要交换才能拥有void exchange(nameType *&amp;a, nameType *&amp;b) 或类似的签名。我希望这会有所帮助。
【解决方案2】:

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

一个常见的瓶颈是文件输入和输出。您可以通过减少或优化瓶颈来使您的程序更快。

从一个文件中读取许多小块数据比读取一个大块数据花费更多的时间。例如,一个请求读取 10 行数据比 10 个请求读取一行数据效率更高。

访问内存很快,比从文件中读取要快。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-19
    • 2018-08-23
    • 1970-01-01
    • 2021-05-11
    • 2012-02-02
    • 1970-01-01
    相关资源
    最近更新 更多