一个关于大量数据导入到2维vector的问题,求教!

v82205 2016-09-19 09:22:21
最近在写一个关于信号处理的程序,但是前期的信号数据导入一直是一个问题,导入速度很慢。
数据类型是double,类似于5.8774718e-39这样的科学计数法(数据的部分内容上传到图片上了),大小为128*3300,存在一个txt文档里,数据是我自己用matlab生成然后导出到txt的。
现在就是想用C++将txt里的数据导入到一个128*3300的二维vector里,下面是代码,处理速度比较慢,要3s多,即使把push_back注释掉还是需要2s多,这种速度有点慢...希望大神们给点看法,谢谢!!
int main()
{
ifstream ifs("..//pre.txt");
vector<vector<double>> data_all(128);
stringstream buffer;
buffer << ifs.rdbuf();
string contents = buffer.str();
string::size_type pos1 = 0, n = 0;
int i = 0;
while ((pos1 = contents.find_first_of("+-.0123456789e", pos1)) != string::npos)
{
auto pos2 = contents.find_first_not_of("+-.0123456789e", pos1);
n = pos2 - pos1;
double d = stod(contents.substr(pos1, n));
data_all[i].push_back(d);
pos1 += n;
if ((i != 127) && (contents[pos1] == '\n'))
++i;
}
}
...全文
526 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
v82205 2016-09-22
  • 打赏
  • 举报
回复
引用 20 楼 cutmelon 的回复:
[quote=引用 19 楼 v82205 的回复:] [quote=引用 14 楼 cutmelon 的回复:] 科学记数法可以直接读的啊
int main()
{
	const int row=128;
	const int column=3300;

	ifstream ifs("..//pre.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
			buffer>>data_all[i][j];

	return 0;
}
你好,我用你的代码测试耗时7s多,在release模式下...还是有点慢啊..[/quote]我没测时间,看来直接转有点慢。换个写法,release测出来0.2秒多
int main()
{
	//写个测试文件
	//ofstream of("d:/1.txt");
	//for (int i=0;i<128*3300;i++)
	//	of.write("5.8774718e-39 ",14);
	//of.flush();

	time_t start=clock();

	const int row=128;
	const int column=3300;

	ifstream ifs("d:/1.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	string tmp;
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
		{
			buffer>>tmp;
			data_all[i][j]=stod(tmp);
		}

	time_t end=clock();
	cout<<"the running time is : "<<double(end-start)/CLOCKS_PER_SEC<<endl;

	return 0;
}
[/quote] 好的,非常感谢!
cutmelon 2016-09-22
  • 打赏
  • 举报
回复
引用 19 楼 v82205 的回复:
[quote=引用 14 楼 cutmelon 的回复:] 科学记数法可以直接读的啊
int main()
{
	const int row=128;
	const int column=3300;

	ifstream ifs("..//pre.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
			buffer>>data_all[i][j];

	return 0;
}
你好,我用你的代码测试耗时7s多,在release模式下...还是有点慢啊..[/quote]我没测时间,看来直接转有点慢。换个写法,release测出来0.2秒多
int main()
{
	//写个测试文件
	//ofstream of("d:/1.txt");
	//for (int i=0;i<128*3300;i++)
	//	of.write("5.8774718e-39 ",14);
	//of.flush();

	time_t start=clock();

	const int row=128;
	const int column=3300;

	ifstream ifs("d:/1.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	string tmp;
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
		{
			buffer>>tmp;
			data_all[i][j]=stod(tmp);
		}

	time_t end=clock();
	cout<<"the running time is : "<<double(end-start)/CLOCKS_PER_SEC<<endl;

	return 0;
}
v82205 2016-09-22
  • 打赏
  • 举报
回复
引用 14 楼 cutmelon 的回复:
科学记数法可以直接读的啊
int main()
{
	const int row=128;
	const int column=3300;

	ifstream ifs("..//pre.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
			buffer>>data_all[i][j];

	return 0;
}
你好,我用你的代码测试耗时7s多,在release模式下...还是有点慢啊..
  • 打赏
  • 举报
回复
引用 15 楼 v82205 的回复:
[quote=引用 13 楼 u012947309 的回复:] 楼上有人提到了,对vector做太多次操作。 我之前也有一个txt导入的代码,试了一下用vector比用数组慢了六七倍...越多越慢。 如果你不知道有多少数据要导入,干脆开一个巨大的数组,然后实时counter。 ps:matlab你输出数一定要输科学计数法吗-。-看起来用起来都比较别扭吧-。-
谢谢回复,看的C++primer上说的能用vector的地方最好用vector,可能我思维僵化了...还有就是数值太小,如果不是科学技术法的话,一串0看起来有点不舒服。。[/quote] 两个一组,可以定义一个结构体point 然后vector<point>这样来做。
paschen 版主 2016-09-20
  • 打赏
  • 举报
回复
先为vector预分配足够大小的空间( reserve ),这样不会随着插入频繁重分配
red-fly 2016-09-20
  • 打赏
  • 举报
回复
既然数量固定,那直接分配一个二维数组更方便,或者是分配一个一维数组,但是要分行进行放置和读取。 如果数量大致固定,不会相差太多,也可以用二维数组,只需要按照最大的数量去分配空间就可以了,这样更方便。
勤奋的小游侠 2016-09-20
  • 打赏
  • 举报
回复
你里面做太多的查找了。 数字和数字之间隔的是空格或者tab。你可以用这一点将值分开。
v82205 2016-09-20
  • 打赏
  • 举报
回复
引用 2 楼 bluewanderer 的回复:
恒定列数不要用二维vector,自己写个二维容器或者用OpenCV的Mat。如果不是实在懒得不行不要挨个substr在stod,直接在原来的字符串里strtod。不过我还是赌你没开优化。
确实是没开优化...然后就是strtod是C标准库里的字符串转double函数,总觉着C和C++的函数混在一块用有点膈应...strtod可以将所有的字符串全部转换为double吗?不用将字符串分开是吗?感谢!
v82205 2016-09-20
  • 打赏
  • 举报
回复
引用 1 楼 lu3664198 的回复:
我试了试,在我的机器128*4096只需要700ms(release模式(你是不是在debug模式呀)),注释掉stod只需要300多ms(应该可以在stod下手(至于std::stod的效率是不是最快我也不知道)).
我一直都用的是debug模式,一般都是在什么情况下使用release啊..请教
v82205 2016-09-20
  • 打赏
  • 举报
回复
引用 14 楼 cutmelon 的回复:
科学记数法可以直接读的啊
int main()
{
	const int row=128;
	const int column=3300;

	ifstream ifs("..//pre.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
			buffer>>data_all[i][j];

	return 0;
}
很棒,明天我试试,谢谢回复!
NoEdUl 2016-09-20
  • 打赏
  • 举报
回复
引用 15 楼 v82205 的回复:
[quote=引用 13 楼 u012947309 的回复:] 楼上有人提到了,对vector做太多次操作。 我之前也有一个txt导入的代码,试了一下用vector比用数组慢了六七倍...越多越慢。 如果你不知道有多少数据要导入,干脆开一个巨大的数组,然后实时counter。 ps:matlab你输出数一定要输科学计数法吗-。-看起来用起来都比较别扭吧-。-
谢谢回复,看的C++primer上说的能用vector的地方最好用vector,可能我思维僵化了...还有就是数值太小,如果不是科学技术法的话,一串0看起来有点不舒服。。[/quote] 可能用vector不会像玩数组动不动就溢出,下标指错,甚至忘记delete吧-。- 安全方便好用确实。 恩,一般遇到很小的0.00000000000x啥的,我同事都是乘以个1000倍。 或者把整数部分和小数部分分开存。 不过楼上有人说可以以科学计数法读数,新技能get!
v82205 2016-09-20
  • 打赏
  • 举报
回复
引用 13 楼 u012947309 的回复:
楼上有人提到了,对vector做太多次操作。 我之前也有一个txt导入的代码,试了一下用vector比用数组慢了六七倍...越多越慢。 如果你不知道有多少数据要导入,干脆开一个巨大的数组,然后实时counter。 ps:matlab你输出数一定要输科学计数法吗-。-看起来用起来都比较别扭吧-。-
谢谢回复,看的C++primer上说的能用vector的地方最好用vector,可能我思维僵化了...还有就是数值太小,如果不是科学技术法的话,一串0看起来有点不舒服。。
cutmelon 2016-09-20
  • 打赏
  • 举报
回复
科学记数法可以直接读的啊
int main()
{
	const int row=128;
	const int column=3300;

	ifstream ifs("..//pre.txt");
	stringstream buffer;
	buffer<<ifs.rdbuf();

	vector<vector<double>> data_all(row,vector<double>(column));
	for (int i=0;i<row;i++)
		for (int j=0;j<column;j++)
			buffer>>data_all[i][j];

	return 0;
}
NoEdUl 2016-09-20
  • 打赏
  • 举报
回复
楼上有人提到了,对vector做太多次操作。 我之前也有一个txt导入的代码,试了一下用vector比用数组慢了六七倍...越多越慢。 如果你不知道有多少数据要导入,干脆开一个巨大的数组,然后实时counter。 ps:matlab你输出数一定要输科学计数法吗-。-看起来用起来都比较别扭吧-。-
bluewanderer 2016-09-20
  • 打赏
  • 举报
回复
引用 4 楼 v82205 的回复:
引用 2 楼 bluewanderer 的回复:
恒定列数不要用二维vector,自己写个二维容器或者用OpenCV的Mat。如果不是实在懒得不行不要挨个substr在stod,直接在原来的字符串里strtod。不过我还是赌你没开优化。
确实是没开优化...然后就是strtod是C标准库里的字符串转double函数,总觉着C和C++的函数混在一块用有点膈应...strtod可以将所有的字符串全部转换为double吗?不用将字符串分开是吗?感谢!
strtod也是一次转一个... 这个倒不是太严重问题。你这样相当于对于每个数都要申请内存建一个新字符串,转换完了就立马释放了。相当地浪费,但也不至于构成灾难... strtod你只要给指向原字符串的指针。或者,你可以用C++17的string_view...
  • 打赏
  • 举报
回复
double d = stod(contents.substr(pos1, n)); 这个可以用>>代替,可能会快一点。 如果事先知道数量,还是用二维数组快一点。
Ulyo 2016-09-20
  • 打赏
  • 举报
回复
引用 4 楼 v82205 的回复:
引用 2 楼 bluewanderer 的回复:
恒定列数不要用二维vector,自己写个二维容器或者用OpenCV的Mat。如果不是实在懒得不行不要挨个substr在stod,直接在原来的字符串里strtod。不过我还是赌你没开优化。
确实是没开优化...然后就是strtod是C标准库里的字符串转double函数,总觉着C和C++的函数混在一块用有点膈应...strtod可以将所有的字符串全部转换为double吗?不用将字符串分开是吗?感谢!
debug模式会有很多检查,比如判断越界什么的... 如果想效率可以考虑下9楼赵4老师那样 如果想简单点,可以用std::istream_iterator(《c++ Primer》 10.4.2)
int main()
{
	const int Column = 128;
	const int Row = 4096;

	std::ifstream ifs("D:\\2.txt");
	std::istream_iterator<std::string> buffer(ifs);
	std::vector<std::vector<double>> data_all(Row);

	//std::cout << std::setprecision(8);

	for (int i = 0; i < Row; ++i)
	{
		data_all[i].reserve(Column);

		for (int j = 0; j < Column; ++j)
		{
			data_all[i].push_back(std::stod(*(buffer++)));

			//std::cout << data_all[i].back() << " ";
			//Sleep(500);
		}
	}
}
赵4老师 2016-09-20
  • 打赏
  • 举报
回复
v82205 2016-09-20
  • 打赏
  • 举报
回复
引用 7 楼 paschen 的回复:
先为vector预分配足够大小的空间( reserve ),这样不会随着插入频繁重分配
这个我测试过了,不会减少太多时间的..
bluewanderer 2016-09-20
  • 打赏
  • 举报
回复
恒定列数不要用二维vector,自己写个二维容器或者用OpenCV的Mat。如果不是实在懒得不行不要挨个substr在stod,直接在原来的字符串里strtod。不过我还是赌你没开优化。
加载更多回复(1)

64,636

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧