我的做法是这样的
1. 将样本拷贝
2. 生成随机样本的位置索引
3. fread原数据的一个样本
4. 根据位置索引调用fseek,找到在随机化之后的位置
5. fwrite这个样本的数据到拷贝的文件中
这个过程极其耗时,但是我将fread, fseek, fwrite三个函数随便选一个注释掉,效率都会有大幅度提升,不知道这是为什么?
13 个解决方案
#1
数据量很大吗,没完全明白你的意思, 打乱(读取出来在写回去?),生成索引(索引存在哪里),按索引查找(怎么查找),你仔细想想你的逻辑处理上有没有可优化的。
#2
数据量很大,400万的样本量,是写到拷贝的样本里面,肯定不能直接写到原样本,这样就覆盖了,索引是提前生成好的,每次都要fread这个索引文件来获取fseek的位置
#3
我是用MATLAB的randperm来生成的索引 = =
#4
仅供参考:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int d[6];
int i,n,a,b,t;
int c,j;
void main() {
srand(time(NULL));
printf("shuffle 0..n-1 demo\n");
for (n=1;n<=5;n++) {/* 测试1~5个元素 */
printf("_____n=%d_____\n",n);
j=1;
for (c=1;c<=n;c++) j=j*c;/* j为n! */
j*=n*2;
for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
for (i=0;i<n;i++) d[i]=i;/* 填写0~n-1 */
for (i=n;i>0;i--) {/* 打乱0~n-1 */
a=i-1;b=rand()%i;
if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
}
printf("%04d:",c);
for (i=0;i<n;i++) printf("%d",d[i]);
printf("\n");
}
}
printf("shuffle 1..n demo\n");
for (n=1;n<=5;n++) {/* 测试1~5个元素 */
printf("_____n=%d_____\n",n);
j=1;
for (c=1;c<=n;c++) j=j*c;/* j为n! */
j*=n*2;
for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
for (i=1;i<=n;i++) d[i]=i;/* 填写1~n */
for (i=n;i>1;i--) {/* 打乱1~n */
a=i;b=rand()%i+1;
if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
}
printf("%04d:",c);
for (i=1;i<=n;i++) printf("%d",d[i]);
printf("\n");
}
}
}
#5
再供参考:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
unsigned long ulrand(void) {
return (
(((unsigned long)rand()<<24)&0xFF000000ul)
|(((unsigned long)rand()<<12)&0x00FFF000ul)
|(((unsigned long)rand() )&0x00000FFFul));
}
unsigned __int64 ullrand(void) {
return (
(((unsigned __int64)ulrand())<<32)
| ((unsigned __int64)ulrand()));
}
int i;
unsigned long ul;
unsigned __int64 ull;
void main() {
srand(time(NULL));
for (i=0;i<10;i++) {
ul=ulrand();
printf("%010lu 0x%08x\n",ul,ul);
}
for (i=0;i<10;i++) {
ull=ullrand();
printf("%020I64u 0x%016I64x\n",ull,ull);
}
}
//3971076432 0xecb1d150
//2433428051 0x910b2a53
//1415415336 0x545d8628
//1312330759 0x4e389407
//1845758378 0x6e0409aa
//0008069933 0x007b232d
//4202720757 0xfa806df5
//2669855255 0x9f22c217
//0312068736 0x1299ca80
//2084555989 0x7c3fccd5
//03502077880857307931 0x3099e1472040ab1b
//16884702393146816355 0xea52835e19b43763
//01877364819396611730 0x1a0dbd5b45f34e92
//07839440151924835771 0x6ccb4948756a05bb
//09471412086917299176 0x8371371c820bfbe8
//04411255971577469925 0x3d37edef2f321be5
//13735846279546091130 0xbe9f876a65b7367a
//04512980766520059820 0x3ea15418aa9927ac
//15821377118299441610 0xdb90d2a9f1bb49ca
//15512417228822200185 0xd7472d480398bf79
#6
有 io 操作当然耗时.加上大量的 fseek (如果是非固态硬盘会跳硬盘磁头....巨耗时)
内存够大,一般都采用 空间换时间 的方法.
1) 采用内存映射文件方法进行操作,
2), 采用 一次 fread() 所以数据,---> 处理 ----> 一次 fwrite()所有数据
// -------------------------------------------
记得N久久前实现一数据整理功能.
用边读边处理边写方法 耗时: 吸一根烟时间
一次读入处理一次写方法 耗时: 点一根烟时间
内存够大,一般都采用 空间换时间 的方法.
1) 采用内存映射文件方法进行操作,
2), 采用 一次 fread() 所以数据,---> 处理 ----> 一次 fwrite()所有数据
// -------------------------------------------
记得N久久前实现一数据整理功能.
用边读边处理边写方法 耗时: 吸一根烟时间
一次读入处理一次写方法 耗时: 点一根烟时间
#7
高兴了楼主试试将文件放在RAMDISK上,估计打火机没从兜里掏出来就over了。
#8
7个G的数据啊……读入内存不现实啊,还是说把7个G拆成小部分分别处理?
#9
多谢多谢,我看看,感觉好高端= =
#10
现在Win64位系统高配的话,内存是多少G来着?
#11
提醒楼主:超过2GB的文件好象不能用fseek得改用_fseeki64(Windows)或fseeko64(Linux)了吧。
#12
我这并没有报错,7个G的文件……
#13
那可能是因为你用64位编译环境且在64系统下运行。
#1
数据量很大吗,没完全明白你的意思, 打乱(读取出来在写回去?),生成索引(索引存在哪里),按索引查找(怎么查找),你仔细想想你的逻辑处理上有没有可优化的。
#2
数据量很大吗,没完全明白你的意思, 打乱(读取出来在写回去?),生成索引(索引存在哪里),按索引查找(怎么查找),你仔细想想你的逻辑处理上有没有可优化的。
数据量很大,400万的样本量,是写到拷贝的样本里面,肯定不能直接写到原样本,这样就覆盖了,索引是提前生成好的,每次都要fread这个索引文件来获取fseek的位置
#3
数据量很大吗,没完全明白你的意思, 打乱(读取出来在写回去?),生成索引(索引存在哪里),按索引查找(怎么查找),你仔细想想你的逻辑处理上有没有可优化的。
我是用MATLAB的randperm来生成的索引 = =
#4
仅供参考:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int d[6];
int i,n,a,b,t;
int c,j;
void main() {
srand(time(NULL));
printf("shuffle 0..n-1 demo\n");
for (n=1;n<=5;n++) {/* 测试1~5个元素 */
printf("_____n=%d_____\n",n);
j=1;
for (c=1;c<=n;c++) j=j*c;/* j为n! */
j*=n*2;
for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
for (i=0;i<n;i++) d[i]=i;/* 填写0~n-1 */
for (i=n;i>0;i--) {/* 打乱0~n-1 */
a=i-1;b=rand()%i;
if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
}
printf("%04d:",c);
for (i=0;i<n;i++) printf("%d",d[i]);
printf("\n");
}
}
printf("shuffle 1..n demo\n");
for (n=1;n<=5;n++) {/* 测试1~5个元素 */
printf("_____n=%d_____\n",n);
j=1;
for (c=1;c<=n;c++) j=j*c;/* j为n! */
j*=n*2;
for (c=1;c<=j;c++) {/* 测试n*2*n!次 */
for (i=1;i<=n;i++) d[i]=i;/* 填写1~n */
for (i=n;i>1;i--) {/* 打乱1~n */
a=i;b=rand()%i+1;
if (a!=b) {t=d[a];d[a]=d[b];d[b]=t;}
}
printf("%04d:",c);
for (i=1;i<=n;i++) printf("%d",d[i]);
printf("\n");
}
}
}
#5
再供参考:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
unsigned long ulrand(void) {
return (
(((unsigned long)rand()<<24)&0xFF000000ul)
|(((unsigned long)rand()<<12)&0x00FFF000ul)
|(((unsigned long)rand() )&0x00000FFFul));
}
unsigned __int64 ullrand(void) {
return (
(((unsigned __int64)ulrand())<<32)
| ((unsigned __int64)ulrand()));
}
int i;
unsigned long ul;
unsigned __int64 ull;
void main() {
srand(time(NULL));
for (i=0;i<10;i++) {
ul=ulrand();
printf("%010lu 0x%08x\n",ul,ul);
}
for (i=0;i<10;i++) {
ull=ullrand();
printf("%020I64u 0x%016I64x\n",ull,ull);
}
}
//3971076432 0xecb1d150
//2433428051 0x910b2a53
//1415415336 0x545d8628
//1312330759 0x4e389407
//1845758378 0x6e0409aa
//0008069933 0x007b232d
//4202720757 0xfa806df5
//2669855255 0x9f22c217
//0312068736 0x1299ca80
//2084555989 0x7c3fccd5
//03502077880857307931 0x3099e1472040ab1b
//16884702393146816355 0xea52835e19b43763
//01877364819396611730 0x1a0dbd5b45f34e92
//07839440151924835771 0x6ccb4948756a05bb
//09471412086917299176 0x8371371c820bfbe8
//04411255971577469925 0x3d37edef2f321be5
//13735846279546091130 0xbe9f876a65b7367a
//04512980766520059820 0x3ea15418aa9927ac
//15821377118299441610 0xdb90d2a9f1bb49ca
//15512417228822200185 0xd7472d480398bf79
#6
有 io 操作当然耗时.加上大量的 fseek (如果是非固态硬盘会跳硬盘磁头....巨耗时)
内存够大,一般都采用 空间换时间 的方法.
1) 采用内存映射文件方法进行操作,
2), 采用 一次 fread() 所以数据,---> 处理 ----> 一次 fwrite()所有数据
// -------------------------------------------
记得N久久前实现一数据整理功能.
用边读边处理边写方法 耗时: 吸一根烟时间
一次读入处理一次写方法 耗时: 点一根烟时间
内存够大,一般都采用 空间换时间 的方法.
1) 采用内存映射文件方法进行操作,
2), 采用 一次 fread() 所以数据,---> 处理 ----> 一次 fwrite()所有数据
// -------------------------------------------
记得N久久前实现一数据整理功能.
用边读边处理边写方法 耗时: 吸一根烟时间
一次读入处理一次写方法 耗时: 点一根烟时间
#7
高兴了楼主试试将文件放在RAMDISK上,估计打火机没从兜里掏出来就over了。
#8
有 io 操作当然耗时.加上大量的 fseek (如果是非固态硬盘会跳硬盘磁头....巨耗时)
内存够大,一般都采用 空间换时间 的方法.
1) 采用内存映射文件方法进行操作,
2), 采用 一次 fread() 所以数据,---> 处理 ----> 一次 fwrite()所有数据
// -------------------------------------------
记得N久久前实现一数据整理功能.
用边读边处理边写方法 耗时: 吸一根烟时间
一次读入处理一次写方法 耗时: 点一根烟时间
7个G的数据啊……读入内存不现实啊,还是说把7个G拆成小部分分别处理?
#9
高兴了楼主试试将文件放在RAMDISK上,估计打火机没从兜里掏出来就over了。
多谢多谢,我看看,感觉好高端= =
#10
现在Win64位系统高配的话,内存是多少G来着?
#11
提醒楼主:超过2GB的文件好象不能用fseek得改用_fseeki64(Windows)或fseeko64(Linux)了吧。
#12
提醒楼主:超过2GB的文件好象不能用fseek得改用_fseeki64(Windows)或fseeko64(Linux)了吧。
我这并没有报错,7个G的文件……
#13
提醒楼主:超过2GB的文件好象不能用fseek得改用_fseeki64(Windows)或fseeko64(Linux)了吧。
我这并没有报错,7个G的文件……
那可能是因为你用64位编译环境且在64系统下运行。