如何在卷积程序的 c++ 中优化嵌套循环
How to optimize nested loop in c++ for a convolution program
我是新手,我有一个卷积程序,可以接收一个数据文件,卷积它并输出另一个文件。我在这里附加代码。
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;
}
我想知道,我能做些什么来加速主卷积发生的部分,我的数据文件非常大,需要很长时间才能完成。需要帮助。
由于嵌套的 for 循环,只有执行卷积的代码部分的运行时间为 T(n( = 5n2+ ....对于 n 较大的文件,这显然是相当低效的。
要解决此问题,您需要减少只有一行代码的 for 循环的数量。如果遍历整个数组,请在一次传递中执行尽可能多的操作。为了优化这一点,您需要重新构建执行逻辑的方式,以便尽可能少地使用 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 循环中。这使得更明显的是那里发生了一些事情,并且您仍然不需要使用括号(只要代码只有一行长(。
我试图删除你们中的一些循环。 请随时询问我的评论是否还不够。
#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();
}
我无法测试它 - 所以这取决于你。
相关文章:
- 空基优化子对象的地址
- 关闭||运算符优化
- 如何解决gcc编译器优化导致的centos双编译器设置中的分段错误
- 返回值优化:显式移动还是隐式
- 人脸跟踪arduino代码的优化
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 纯函数,为什么没有优化
- 为什么大多数 pair 实现默认不使用压缩(空基优化)?
- 如何以优化的方式同时迭代两个间距不相等的数组
- 小字符串优化(调试与发布模式)
- 浮点定向舍入和优化
- Visual Studio 调试优化如何工作?
- 为什么开关的优化方式与 c/c++ 中的链接不同?
- 线性优化目标函数中的绝对值
- GCC 会优化内联访问器吗?
- gcc 如何优化此循环?
- 如何防止 CUDA-GDB 中的<优化输出>值
- 为什么我的程序在 O0 和 O2 的优化级别返回不同的结果
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 使用 std::p air 进行返回值优化