🔒 Locked
fast array writing
Advertisement
Original Post
I ''m working on an image application and I need to fill an array of 800 * 600 * 6 floats in c. Nevertheless, I don''t manage to fill it fast enough. I would like to fill it in 15ms, but it takes me 50ms by a simple loop:
for(i = 800; i--
{
for(j = 600; j--
{
*(ptr++) = x;
*(ptr++) = y;
*(ptr++) = z;
*(ptr++) = x;
*(ptr++) = y + 1.0f;
*(ptr++) = x;
}
}
Can I improve this by an optimzed code (for pentium for example)?
I don''t see why you need 6 floating point values to store a pixel, unless the image contains colours that can''t normally be seen by the human eye. 192 bits per pixel is silly. Why can''t you just use 24bpp (3 bytes, one for red, blue, and green) like everyone else?
First off, just use one loop instead of 2.
Secondly, don''t calculate the y+1.0f each time through (although the compiler might notice that it doesn''t have to).
Try something like this :
This takes advantage of the fact that memcpy doesn''t try to do anything clever when the source and destination regions overlap (that''s what memmove does). Most modern compilers have a well-optimised implementation of memcpy that works well.
Iain Hutchison
Programmer, Silicon Dreams
The views expressed here are my own, not those of my employer.
Secondly, don''t calculate the y+1.0f each time through (although the compiler might notice that it doesn''t have to).
Try something like this :
*(ptr+0) = x;
*(ptr+1) = y;
*(ptr+2) = z;
*(ptr+3) = x;
*(ptr+4) = y + 1.0f;
*(ptr+5) = x;
memcpy(ptr+6, ptr, (800*600-1)*6*sizeof(float));
This takes advantage of the fact that memcpy doesn''t try to do anything clever when the source and destination regions overlap (that''s what memmove does). Most modern compilers have a well-optimised implementation of memcpy that works well.
Iain Hutchison
Programmer, Silicon Dreams
The views expressed here are my own, not those of my employer.
untested but still worth a try, since your initialization does not read anything from your array:
could you create a small array of floats to initialize it and then use memcpy to initialize your array:
Could you test it ?
Ghostly yours,
Red.
could you create a small array of floats to initialize it and then use memcpy to initialize your array:
float[6] mini_array
int array_width
mini_array[0]=x
mini_array[1]=y
mini_array[2]=z
mini_array[3]=x
mini_array[4]=y + 1.0f
mini_array[5]=z
array_width = sizeof (mini_array)
i = 800 * 600
while (i > 0)
{
memcpy(ptr, mini_array, array_width)
ptr+= array_width
i--
}
Could you test it ?
Ghostly yours,
Red.
Sorry I haven''t been very clear, but in fact my problem is that I need to do a transfer from a large array to an vertices array. For the moment the filling of the array is made linearly whereas the access of the large array is made non-linearly. In pseudo-code:
for (y = sideY; y--
{
for (x = sideX; x--
{
index = f(x, y)
v = largeArray[index]
*(ptrZbuffer++) = v.x;
*(ptrZbuffer++) = v.y;
*(ptrZbuffer++) = v.z;
*(ptrZbuffer++) = v.x;
*(ptrZbuffer++) = v.y + 1.0f;
*(ptrZbuffer++) = v.z;
}
}
are there any methods to optimize this data transfer?
thank you
for (y = sideY; y--
{
for (x = sideX; x--
{
index = f(x, y)
v = largeArray[index]
*(ptrZbuffer++) = v.x;
*(ptrZbuffer++) = v.y;
*(ptrZbuffer++) = v.z;
*(ptrZbuffer++) = v.x;
*(ptrZbuffer++) = v.y + 1.0f;
*(ptrZbuffer++) = v.z;
}
}
are there any methods to optimize this data transfer?
thank you
Two words : Duff''s device
anonymous is correct about the bandwidth. i was looking into efficiency for my program and found that memory bandwidth was my problem too. maybe it''ll be faster if you organize the structure of the structure so you can do a memcpy. then, instead of using a normal memcpy, use a sse/mmx/3dnow memcpy. i don''t know if your compiler is already optimized memcpy or not, but i read somewhere that you can get up to a 400% increase.
and about that "Duff''s device"
how come the *to in *to = *from++; doesn''t have a ++? i know its mentioned in the notes but i don''t get it
and about that "Duff''s device"
how come the *to in *to = *from++; doesn''t have a ++? i know its mentioned in the notes but i don''t get it
Because the loop he was originally unrolling was
Don''t ask me why.
[Questions (STFW) | GDNet Start Here | GDNet Search | Forum FAQ | Google | Asking Smart Questions ]
[Docs (RTFM) | MSDN | SGI''s STL | OpenGL | File formats]
[C++ Must Haves (RTFS) | MinGW | Boost | Loki | FLTK | SDL ]
Stolen from Magmai Kai Holmlor, who held it from Oluseyi, who was inspired by Kylotan...
do
*to = *from++
while (count-->0)
Don''t ask me why.
[Questions (STFW) | GDNet Start Here | GDNet Search | Forum FAQ | Google | Asking Smart Questions ]
[Docs (RTFM) | MSDN | SGI''s STL | OpenGL | File formats]
[C++ Must Haves (RTFS) | MinGW | Boost | Loki | FLTK | SDL ]
Stolen from Magmai Kai Holmlor, who held it from Oluseyi, who was inspired by Kylotan...
Not if you are writing to a memory-mapped IO device (as the comment explicitely points out) : each time you write to the device''s address, you are actually sending the data (say, through a serial line). If you are actually copying from/to memory, you would write *to++.
[Questions (STFW) | GDNet Start Here | GDNet Search | Forum FAQ | Google | Asking Smart Questions ]
[Docs (RTFM) | MSDN | SGI''s STL | OpenGL | File formats]
[C++ Must Haves (RTFS) | MinGW | Boost | Loki | FLTK | SDL ]
Stolen from Magmai Kai Holmlor, who held it from Oluseyi, who was inspired by Kylotan...
[Questions (STFW) | GDNet Start Here | GDNet Search | Forum FAQ | Google | Asking Smart Questions ]
[Docs (RTFM) | MSDN | SGI''s STL | OpenGL | File formats]
[C++ Must Haves (RTFS) | MinGW | Boost | Loki | FLTK | SDL ]
Stolen from Magmai Kai Holmlor, who held it from Oluseyi, who was inspired by Kylotan...
quote:
Original post by Fruny
Two words : Duff''s device
Duff''s is a cool contraption and it will speed up unoptimized code - but it won''t gain much over compiler optimization - at least in my experience. Where Duff''s really shines is that it allows for unlooping an odd number of elements - you don''t have to worry if the transfer size is evenly divisible by 8. Duff''s also shines when used in interpretted code - like scripts.
well i hate to say it, but even my pentium4 1500 with rdram has trouble moving all that data within 15ms. why do you need so many values? if you want realtime results you will have to use a lower resolution. what exactly are you doing? seems to me that you are looking at things the wrong way. you either get good quality or fast speed. you cant have both. no amount of code optimization will get you your magic speed, using sse, mmx, 3dnow, etc will not help much. explain what you are trying to do, maybe someone can help point you in a better direction with an algorithm that does not require such large transfers. look into transfering only what is needed (which must be able to be done without checking each piece of data for a flag). maybe using ditry rects?
What is the function you use to calculate the array index ?
If it is intensive in calculation, either you could simplify it (to obtain something like index += constant to advance in your array) or you could precalculate the index values.
If the function calculating the index changes during the program execution, well there isn''t much to do.
Another approach you may try is to reduce the pointer calculation (the gain might not be much however):
Besides memory bandwidth, the optimization of the index function is important.
Hope that helps.
Ghostly yours,
Red.
If it is intensive in calculation, either you could simplify it (to obtain something like index += constant to advance in your array) or you could precalculate the index values.
If the function calculating the index changes during the program execution, well there isn''t much to do.
Another approach you may try is to reduce the pointer calculation (the gain might not be much however):
int size;
size = sizeof(v)
for (y= 600; y--;)
for (x= 800; x--;)
index = f(x,y)
v = large_array[index]
memcpy(ptr, v, size)
v.y += 1.0f
ptr += size
memcpy(ptr, v, size)
ptr += size
Besides memory bandwidth, the optimization of the index function is important.
Hope that helps.
Ghostly yours,
Red.
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement