Skip to main content
gamedev.net
🔒 Locked

fast array writing

Started by ylegoc Apr 22, 2002 at 9:22 AM 13 replies 400+ views
Original Post
ylegoc
ylegoc
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)?
smart_idiot
smart_idiot
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?
Chess is played by three people. Two people play the game; the third provides moral support for the pawns. The object of the game is to kill your opponent by flinging captured pieces at his head. Since the only piece that can be killed is a pawn, the two armies agree to meet in a pawn-infested area (or even a pawn shop) and kill as many pawns as possible in the crossfire. If the game goes on for an hour, one player may legally attempt to gouge out the other
pieman
pieman
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 :

*(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.
Iain HutchisonProgrammer, Silicon DreamsThe views expressed here are my own, not those of my employer.
Red Ghost
Red Ghost
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:


  
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.
Ghostly yours,Red.
ylegoc
ylegoc
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
Fruny
Fruny
Two words : Duff''s device
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
thuned
thuned
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
life is unfair, take advantage of it.UNMB2 - if the link doesn't work, try clicking it :)
Fruny
Fruny
Because the loop he was originally unrolling was

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...
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
thuned
thuned
yeah, but doesn''t it "fall through" and the value stored at to (*to) gets overwritten as it falls through the cases?
life is unfair, take advantage of it.UNMB2 - if the link doesn't work, try clicking it :)
Fruny
Fruny
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...
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
thuned
thuned
oh, so that''s why. interesting; fun learning new things everyday.
life is unfair, take advantage of it.UNMB2 - if the link doesn't work, try clicking it :)
LessBread
LessBread
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.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
a person
a person
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?
Red Ghost
Red Ghost
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):


  
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.
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.