如何在c ++中为卷积程序优化嵌套循环

时间:2017-06-30 13:36:22

标签: c++ for-loop convolution

我是新手,我有一个卷积程序,它接收一个数据文件,卷积它并输出另一个文件。我在这里附上代码。

void convolute()
{
    ifstream fin;
    ofstream fout;

    int count = 0;
    double a=0,b=0;

    string input_file_string = "maxclus_500000node_3M_5000ens_666.dat";

    string output_file_string = "1convolute_"+input_file_string;

    fin.open(input_file_string.c_str());

    while(fin) //to know the size of array to initialize
    {
        fin>>a>>b;
        count++;

    }

    fin.close();
    double* c = NULL;
    c = new double[count+1];
    double* d = NULL;
    d = new double[count+1];

    for(int i=0;i<count+1;i++)
    {
        c[i] = 0;
        d[i] = 0;
    }

    fin.open(input_file_string.c_str());

    int n = 1;

    while(fin) //takes in data
    {
        fin>>a>>b;
        c[n] = a;
        d[n] = b;
        n++;
    }

    fin.close();

    double* binom = NULL;
    binom = new double[count];

    double* summ = NULL;
    summ = new double[count+1];

    for(int i=0;i<count+1;i++) summ[i] = 0;

    for(int i=0;i<count;i++) binom[i] = 0;

    for(int j=1;j<count;++j) //main convolution of data takes place
    {
        int x,y;
        double prob = j*1.0/(count-1);
        binom[j] = 1;

        for(int i=j+1;i<count;++i)
            binom[i] = binom[i-1]*((count-1)-i+1)*1.0/i*prob/(1-prob);

        for(int i=j-1;i>=0;--i)
            binom[i] = binom[i+1]*(i+1)*1.0/((count-1)-i)*(1-prob)/prob;

        double sum = 0;

        for(int i=0;i<count;++i) sum += binom[i];
        for(int i=0;i<count;++i) binom[i] /= sum;

        sum = 0;

        for(int i=1;i<count;++i) sum += d[i]*binom[i];

        summ[j] = sum;

        //fout<<c[j]<<'\t'<<sum<<endl;
        if(j%1000==0)
            cout<<count-1<<'\t'<<j<<endl;

    }

    cout<<"writing to file "<<endl;

    fout.open(output_file_string.c_str());

    for(int i=1;i<count;i++) fout<<c[i]<<'\t'<<summ[i]<<endl;

        fout.close();

    delete [] c;
    c = NULL;
    delete [] d;
    d = NULL;

    delete [] binom;
    binom = NULL;

    delete [] summ;
    summ = NULL;

}

我想知道,我可以做些什么来加速发生主要卷积的部分,我的数据文件非常大,并且需要花费大量时间才能完成。需要帮忙。

2 个答案:

答案 0 :(得分:0)

由于嵌套的for循环,只进行卷积的代码部分的运行时间为T(n)= 5n 2 + ....这显然是相当低效的。 n很大的文件。

要解决此问题,您需要减少只有一行代码的for循环数。如果遍历整个阵列,请在一次通过中执行尽可能多的操作。要优化这一点,您需要重新构建逻辑的方式,以便尽可能少地进行循环。

您需要使用数组吗?向量将提供相同(并且更有效)的目的,因为您可以在文件中读取时添加元素(而不是必须打开文件以获取计数...)。因此,反过来,

vector.size();

给出了向量的大小。此外,只有在要增加元素时,才需要使用整个循环将数组初始化为0。如果您只是分配元素,则将数组初始化为0没有任何意义。

如果所有这些都在一个功能中,那么你真的需要将其拆分。这个函数完全是坏的风格,因为有许多不必要的操作,大量的for循环,函数太长并且本身有很多东西超出了卷积输入的范围。

#include <vector>
#include <fstream>

void convolute(/*data you need*/);

int main() {
  string input_file_string = "maxclus_500000node_3M_5000ens_666.dat";
  string output_file_string = "1convolute_"+input_file_string;

  ifstream fin (input_file_string);
  ofstream fout (output_file_string);

  int count = 0;
  double a=0,b=0;
  vector<double> c;
  vector<double> d;

  while (fin >> a >> b) {
    c.push_back(a);
    d.push_back(d);
  }
  fin.close();

  vector<double> binom;
  vector<double> summ;

  convolute(/*Pass the Data you need*/);
  ...
}

看看这有多简单?使用正确的数据类型可以极大地简化您的生活。另外,为了便于阅读,请将操作放在下一行的for循环中。这使得更明显的是那里有一些东西,你仍然不需要使用括号(只要代码只有一行)。

答案 1 :(得分:0)

我试图删除你的一些循环。 请随意询问我的评论是否不充分。

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <tuple>
#include <algorithm>

using std::cout;
using std::endl;

using std::ifstream;
using std::ofstream;

using std::string;
using std::vector;
using std::pair;

void convolute()
{

    string input_file_string = "maxclus_500000node_3M_5000ens_666.dat";
    string output_file_string = "1convolute_" + input_file_string;


    double a = 0, b = 0;
    vector<pair<double, double>> coordinates;

    ifstream fin;
    fin.open(input_file_string.c_str());
    while (fin)
    {
        fin >> a >> b;
        coordinates.push_back({ a,b });
    }
    fin.close();

    static int count = (int)coordinates.size();
    vector<double> binom(coordinates.size(), 0);
    vector<double> summ(coordinates.size(), 0);

    const double probMul = 1.0 / (coordinates.size() - 1); //Probability multiplicator

    for (int j = 1; j< coordinates.size(); ++j) //main convolution of data takes place
    {
        const double prob = j*probMul;

        binom[j] = 1;

        double sum = binom[j];
        double sum_x = binom[j] * coordinates[j].second; // <- (A/X) + (B/X) +... <=> (A+B+C+...)/X
        for (int i = j + 1; i < count; ++i) //from j+1 to end
        {
            binom[i] = binom[i - 1] * ((count - 1) - i + 1)*1.0 / i*prob / (1 - prob);
            sum += binom[i];
            sum_x += binom[i] * coordinates[i].second;
        }
        for (int i = j - 1; i >= 0; --i)  //from j-1 to front
        {
            binom[i] = binom[i + 1] * (i + 1)*1.0 / ((count - 1) - i)*(1 - prob) / prob;
            sum += binom[i];
            sum_x += binom[i] * coordinates[i].second;
        }

        summ[j] = sum_x / sum;

        if (j % 1000 == 0)
        {
            cout << count - 1 << '\t' << j << endl;
        }
    }


    cout << "writing to file " << endl;

    ofstream fout;
    fout.open(output_file_string.c_str());
    for (int i = 1; i < count; i++)
    {
        fout << coordinates[i].first << '\t' << summ[i] << endl;
    }
    fout.close();
}

我无法测试它 - 所以这取决于你。