On Fri, Mar 19, 2010 at 3:52 PM, Jimmy Johnson <[email protected]> wrote:
[...]
>> Yes. One (or two) allocation(s) instead of many smaller ones. Since
>> you know exactly how many elements you need, a single allocation can be
>> done. Even if you did NOT know how many elements to allocate, it is
>> almost always faster to precalculate how many elements, allocate the
>> amount of memory needed, and then perform the actual manipulation of the
>> memory.
>
> Great! How do I do that?
func1() - your method allocating row by row, then initialising cell by cell
func2() - allocating it on one go , initialising cell by cell
func3() - as func2() but only initialising row 0 cell by cell only,
and copying that row to other rows
Beneath that is some profiling showing a 20% saving in func2() (the 15
and 12 million numbers.) and 87% saving in func3() (2 million number)
[...@pjhdesktop /tmp]# cat x.cpp
#include <stdio.h>
#include <string.h>
double** func1(long width, long height){
double** buffer;
long i, j;
buffer = new double* [width];
for (i = 0; i < width; i++) {
buffer [i] = new double [height];
};
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
buffer[i][j] = -10000;
};
};
return buffer;
}
double* func2(long width, long height){
double* buffer;
long i, j;
buffer = new double [width*height];
for (i = 0; i < width; i++) {
for (j = 0; j < height; j++) {
buffer[i*j] = -10000;
};
};
return buffer;
}
double* func3(long width, long height){
double* buffer;
long i, j;
buffer = new double [width*height];
for (i = 0; i < width; i++) {
buffer[i] = -10000;
}
for (j = 1; j < height; j++) {
memcpy(&buffer[width*j], &buffer[0], (sizeof *buffer)*width);
};
// printf("%g, %g, %g\n", buffer[0], buffer[9*5],
buffer[(width-1)*(height-1)]);
return buffer;
}
int main(void){
long x, y;
x = y = 1000;
func1(x, y);
func2(x, y);
func3(x, y);
}
[...@pjhdesktop /tmp]# make -B x
g++ x.cpp -o x
[...@pjhdesktop /tmp]# valgrind --tool=callgrind --quiet ./x
[...@pjhdesktop /tmp]# callgrind_annotate `ls -rt | tail -n 1`
--------------------------------------------------------------------------------
Profile data file 'callgrind.out.7116' (creator: callgrind-3.5.0)
--------------------------------------------------------------------------------
I1 cache:
D1 cache:
L2 cache:
Timerange: Basic block 0 - 4396874
Trigger: Program termination
Profiled target: ./x (PID 7116, part 1)
Events recorded: Ir
Events shown: Ir
Event sort order: Ir
Thresholds: 99
Include dirs:
User annotated:
Auto-annotation: off
--------------------------------------------------------------------------------
Ir
--------------------------------------------------------------------------------
31,377,182 PROGRAM TOTALS
--------------------------------------------------------------------------------
Ir file:function
--------------------------------------------------------------------------------
15,028,028 ???:func1(long, long) [/tmp/x]
12,013,019 ???:func2(long, long) [/tmp/x]
2,024,148 ???:memcpy [/lib/i686/libc-2.10.1.so]
567,995
/home/tex/BUILD/glibc-2.10.1/elf/../sysdeps/generic/dl-hash.h:do_lookup_x
523,961 /home/tex/BUILD/glibc-2.10.1/elf/dl-lookup.c:_dl_lookup_symbol_x
[/lib/ld-2.10.1.so]
341,585 /home/tex/BUILD/glibc-2.10.1/elf/do-lookup.h:do_lookup_x
[/lib/ld-2.10.1.so]
181,298
/home/tex/BUILD/glibc-2.10.1/elf/../sysdeps/i386/dl-machine.h:_dl_relocate_object
142,682 /home/tex/BUILD/glibc-2.10.1/string/strcmp.c:strcmp
[/lib/ld-2.10.1.so]
128,046 ???:0x0006cba0 [/lib/i686/libc-2.10.1.so]
111,900 /home/tex/BUILD/glibc-2.10.1/elf/do-lookup.h:check_match.8313
[/lib/ld-2.10.1.so]
73,443 ???:_dl_addr [/lib/i686/libc-2.10.1.so]
--
PJH
http://shabbleland.myminicity.com/tra
http://www.chavgangs.com/register.php?referer=9375