C 动态分配速度问题
我正在使用以下代码动态创建二维阵列:C 动态分配速度问题,c,arrays,performance,dynamic,malloc,C,Arrays,Performance,Dynamic,Malloc,我正在使用以下代码动态创建二维阵列: char **FileTables; int rows = 1000; int i; FileTables = (char**)malloc(rows * sizeof(char)); for (i = 0; i < rows; i++) { FileTables[i] = (char*)malloc(256 * sizeof(char)); } (是的,我修复了不必要的施法)您只需两次分配和一些指针运算即可: int rows = 100
char **FileTables;
int rows = 1000;
int i;
FileTables = (char**)malloc(rows * sizeof(char));
for (i = 0; i < rows; i++) {
FileTables[i] = (char*)malloc(256 * sizeof(char));
}
(是的,我修复了不必要的施法)您只需两次分配和一些指针运算即可:
int rows = 1000;
int cols = 256;
char *data;
char **FileTables;
int i;
data = malloc(rows * cols);
FileTables = malloc(rows * sizeof(char*));
for (i = 0; i < rows; i++) {
FileTables[i] = data + i * cols;
}
int行=1000;
int cols=256;
字符*数据;
字符**文件表;
int i;
数据=malloc(行*列);
FileTables=malloc(rows*sizeof(char*));
对于(i=0;i
也注意到我在代码< > Maloc(行*sieZOF(char))< /C>(代码< > CIER(char)< /C> >中应该修复了一个bug,应该是<代码> siZeof(char)< /C> >,因为您正在分配一个指针数组,阿纳尔> < p> >代码> > p> >如果数组总是大小为代码>行< /代码>×256,那么您可以考虑一维数组<代码> Maloc(行* 256)。,并可快速访问:
char get(unsigned i, unsigned j, char * array) { return array[j + 256 * i]; }
void set(char value, unsigned i, unsigned j, char * array) { array[j + 256 * i] = value; }
这避免了多次分配,并提供了更好的内存局部性。除此之外,您还可以选择行或列顺序进行微优化。char**FileTables;
char **FileTables;
int rows = 1000;
int i;
FileTables = (char**)malloc(rows * sizeof(char *));
char *data = (char *)malloc(256 * 1000 * sizeof(char));
for (i = 0; i < rows; ++i) {
FileTables[i] = data;
data += 256 * sizeof(char);
}
int行=1000;
int i;
FileTables=(char**)malloc(rows*sizeof(char*);
char*data=(char*)malloc(256*1000*sizeof(char));
对于(i=0;i
应该是更好的解决方案。首先,您确定内存分配是问题所在吗?分配1000块内存通常不需要几秒钟 如果您有特殊需求,您可以研究其他malloc实现(例如,如果您在线程中分配内存,则可以使用google的tcmalloc)
否则,malloc真正“慢”的部分实际上是从操作系统获取内存(使用sbrk()或mmap()),大多数malloc实现会一次获取一大块内存,然后以较小的部分返回,因此这里没有1000个调用分配1k,可能有60个调用分配16k。在strace或类似模式下运行该程序可能会让您了解实际进行了多少缓慢的系统调用。。您可以自己实现类似的行为,只需调用一次就可以分配256K并将其细分为更小的块。您可以尝试分配一大块内存,然后立即释放(),并希望库malloc保留该内存,而不是返回操作系统获取更多内存。这看起来真的像是过早优化;因为,你要求更快,但你没有指出有多快才算足够快。不过,如果你真的需要这样做 加快分配的提示:
无论哪种方式,如果不详细了解计算机上内存管理子系统的实际设计,就无法保证最佳分配速度。只要列数不变,或者如果使用C99,您可以使用单个
malloc
,而无需自己执行难看的行/列寻址算法:
char (*FileTables)[256] = malloc(rows * sizeof *FileTables);
我不相信你能在几秒钟内到达任何地方。在我的机器上,将行数增加到1000万仍然不到一秒钟 然而,如果你想最小化分配,你只需要一个
FileTables = (char**) malloc(rows * (sizeof(char *) + 256*sizeof(char)));
FileTables[0] = (char *) &FileTables[rows];
for (i = 1; i < rows; i++) {
FileTables[i] = FileTables[i-1] + 256 * sizeof (char);
}
free(FileTables);
这避免了指针查找,因为C可以计算其余部分。注意:您不应该在C中强制转换malloc的结果-这是不必要的,并且可能会掩盖编译器可能警告您的错误。Paul:+1。我真想知道为什么人们会这样做。他们在什么时候说,“嗯,我的代码运行得很好,看起来很棒。我想知道我是否可以通过插入免费的强制转换来给它添加一些噪音。
对于(I=(int)0;(int)I<12;++(int)I)
@Kerrek:++(int)I
不编译。++
需要左值而(int)i
不是左值。保罗:是的,的确,这是一个过度夸张的例子。公平地说,malloc类型转换通常也会改变类型——但不必要的是,因为转换已经是隐式的。注意(注释已删除).1作为答案。我本来打算使用aix发布的解决方案,但这要简单得多,代码也少得多。有人能评论一下哪种方法更好,为什么?我更喜欢我的方法,因为FileTables
的类型是正确的,您可以只编写FileTables[row][col
和FileTables[row]
本身将衰减为指向该行的指针(一个普通的char*
)。您不必自己跟踪算术。我是用通常的free(FileTables);
释放它,还是需要做一些特殊的事情?没错,就是free(FileTables);
。您也可以在其上使用realloc
;只需确保正确计算新尺寸即可。
char (*FileTables)[256] = malloc(rows * sizeof *FileTables);
FileTables = (char**) malloc(rows * (sizeof(char *) + 256*sizeof(char)));
FileTables[0] = (char *) &FileTables[rows];
for (i = 1; i < rows; i++) {
FileTables[i] = FileTables[i-1] + 256 * sizeof (char);
}
free(FileTables);
typedef char chars[256];
int main(int argc, char** argv) {
chars* FileTables;
int rows = 100000000;
int i;
FileTables = (chars*) malloc(rows * sizeof (chars));
free(FileTables);
return (EXIT_SUCCESS);
}