Tech Off Thread

12 posts

Optimization question

Back to Forum: Tech Off
  • User profile image
    Royal​Schrubber

    So I have a couple of floats (ok millions) that I convert to bitmap (it's my pet project - madelbrot renderer - floats come from f(x,y), then I use color gradient info to convert it to RGBs).
     
    I do this in two steps - first generating floats (that's usually slower), then rendering (converting to RGBs/bitmap) - I do this in two steps so that user can dynamically change gradient in real-time.
    I can do 20 fps at 800x600 with no anti-aliasing on core2, but that's too slow if somebody wants to view fractal over whole screen.

    Right now I use 24bit RGB format - but the question is - will my code run faster if I use 32bits per pixel (aRGB) format and use int to write color to a pixel array instead of using 3 bytes?
    That way I'll use 1/3 more RAM bandwidth and use few shift and OR instructions, but on the other hand have 3x less ram operations.

    It's really not that much code to change (couple of hours), but I'm lazy and if you know answer from experience please do tell it to me. I've got a feeling aRGB will work better, am I right? Smiley

    Oh I use C#.

  • User profile image
    nightski

    For a pixel shader - it wouldn't be too difficult.  I would highly recommend using Nvidia's FX Composer 2 - its a great IDE for shaders.  Or if you want to use ATI stuff there is Rendermonkey.

  • User profile image
    Royal​Schrubber

    longnight wrote:
    I’m curios here, I have a lot of fun playing with the Bitmap image buffer in managed C++, but I haven’t found a good way to do this using C#. Can you shed some light on how you’re accessing the image buffer in C#?


    Hey, real magician never reveals his tricks... j/k, it's really easy:

    Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
    BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat);
    int stride = bmpData.Stride;
    byte[] rgbValues = new byte[stride * bmp.Height];
    //fill rgbValues; make sure to jump (stride - width * 3) after each line
    IntPtr ptr = bmpData.Scan0;
    System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, stride * bmp.Height);
    bmp.UnlockBits(bmpData);
    pictureBox1.Image = bmp;

    here I don't use buffer directly but rather copy managed bitmap array back to bitmap object - the advantage is safer code as you don't have to use unsafe keyword and fiddle with pointers, the bad side is performace - that's why I'll probably change code and use ptr directly - (along with using PixelFormat.Format32bppRgb).

    (dunno if you know this - c# can use pointers just like c and c++ - http://msdn2.microsoft.com/en-us/library/y31yhkeb(VS.80).aspx"> http://msdn2.microsoft.com/en-us/library/y31yhkeb(VS.80).aspx)

  • User profile image
    Antitorgo

    Well, I think you'd see a speed increase since you are reducing the instructions in an inner loop there, but not on the order of magnitude that you're looking for.

    My guess is that you'd see a slight increase in performance.

    A better approach is to run a profiler against your code and see where it is actually running slow and then optimize from there.

  • User profile image
    evildictait​or

    Yes. It is much faster to store a color as a DWORD rather than as three BYTEs because RAM access is faster on WORD boundaries and you can read it out to a register in one operation (rather than reading three bytes to three registers).

  • User profile image
    figuerres

    RoyalSchrubber wrote:
    So I have a couple of floats (ok millions) that I convert to bitmap (it's my pet project - madelbrot renderer - floats come from f(x,y), then I use color gradient info to convert it to RGBs).
     
    I do this in two steps - first generating floats (that's usually slower), then rendering (converting to RGBs/bitmap) - I do this in two steps so that user can dynamically change gradient in real-time.
    I can do 20 fps at 800x600 with no anti-aliasing on core2, but that's too slow if somebody wants to view fractal over whole screen.

    Right now I use 24bit RGB format - but the question is - will my code run faster if I use 32bits per pixel (aRGB) format and use int to write color to a pixel array instead of using 3 bytes?
    That way I'll use 1/3 more RAM bandwidth and use few shift and OR instructions, but on the other hand have 3x less ram operations.

    It's really not that much code to change (couple of hours), but I'm lazy and if you know answer from experience please do tell it to me. I've got a feeling aRGB will work better, am I right? Smiley

    Oh I use C#.


    ??  have you seen the demo-sample done with XNA Game STudio ??
    I played with it for a bit, got it to do color (source was shades of gray)
    it uses the GPU pixel shader  function and it creates a "basic" brot fast as heck!

    now I am not sure how to then do all the other things but that speed is just amazing!

    if you are interested I can post some info you could play with, very small code.

    insanely small really.

    but I have not updated it to run with the 2.0 GS bits so It may need some adjustments.

    it runs on the pc or the xbox.

  • User profile image
    Royal​Schrubber

    figuerres wrote:
    
    RoyalSchrubber wrote:
    So I have a couple of floats (ok millions) that I convert to bitmap (it's my pet project - madelbrot renderer - floats come from f(x,y), then I use color gradient info to convert it to RGBs).
     
    I do this in two steps - first generating floats (that's usually slower), then rendering (converting to RGBs/bitmap) - I do this in two steps so that user can dynamically change gradient in real-time.
    I can do 20 fps at 800x600 with no anti-aliasing on core2, but that's too slow if somebody wants to view fractal over whole screen.

    Right now I use 24bit RGB format - but the question is - will my code run faster if I use 32bits per pixel (aRGB) format and use int to write color to a pixel array instead of using 3 bytes?
    That way I'll use 1/3 more RAM bandwidth and use few shift and OR instructions, but on the other hand have 3x less ram operations.

    It's really not that much code to change (couple of hours), but I'm lazy and if you know answer from experience please do tell it to me. I've got a feeling aRGB will work better, am I right? Smiley

    Oh I use C#.


    ??  have you seen the demo-sample done with XNA Game STudio ??
    I played with it for a bit, got it to do color (source was shades of gray)
    it uses the GPU pixel shader  function and it creates a "basic" brot fast as heck!

    now I am not sure how to then do all the other things but that speed is just amazing!

    if you are interested I can post some info you could play with, very small code.

    insanely small really.

    but I have not updated it to run with the 2.0 GS bits so It may need some adjustments.

    it runs on the pc or the xbox.


    Mandelbrot in shader language? Interesting. Got linky, compiled version available or will I have to fiddle with XNA?
    Though I think my fractal generation code is fairly optimized on x86 cores (I did comparison with commercial software and it runs at similar speeds) - though I don't use SSE or anything more advanced. (It's a humble pet project, remember?) Smiley

  • User profile image
    figuerres

    RoyalSchrubber wrote:
    
    figuerres wrote:
    
    RoyalSchrubber wrote:
    So I have a couple of floats (ok millions) that I convert to bitmap (it's my pet project - madelbrot renderer - floats come from f(x,y), then I use color gradient info to convert it to RGBs).
     
    I do this in two steps - first generating floats (that's usually slower), then rendering (converting to RGBs/bitmap) - I do this in two steps so that user can dynamically change gradient in real-time.
    I can do 20 fps at 800x600 with no anti-aliasing on core2, but that's too slow if somebody wants to view fractal over whole screen.

    Right now I use 24bit RGB format - but the question is - will my code run faster if I use 32bits per pixel (aRGB) format and use int to write color to a pixel array instead of using 3 bytes?
    That way I'll use 1/3 more RAM bandwidth and use few shift and OR instructions, but on the other hand have 3x less ram operations.

    It's really not that much code to change (couple of hours), but I'm lazy and if you know answer from experience please do tell it to me. I've got a feeling aRGB will work better, am I right? Smiley

    Oh I use C#.


    ??  have you seen the demo-sample done with XNA Game STudio ??
    I played with it for a bit, got it to do color (source was shades of gray)
    it uses the GPU pixel shader  function and it creates a "basic" brot fast as heck!

    now I am not sure how to then do all the other things but that speed is just amazing!

    if you are interested I can post some info you could play with, very small code.

    insanely small really.

    but I have not updated it to run with the 2.0 GS bits so It may need some adjustments.

    it runs on the pc or the xbox.


    Mandelbrot in shader language? Interesting. Got linky, compiled version available or will I have to fiddle with XNA?
    Though I think my fractal generation code is fairly optimized on x86 cores (I did comparison with commercial software and it runs at similar speeds) - though I don't use SSE or anything more advanced. (It's a humble pet project, remember?) Smiley



    well here is a start:
    http://blogs.msdn.com/shawnhar/archive/2006/12/11/sixty-fractals-per-second.aspx

    that's the stuff I found.

    I took that code and worked on it a bit late last year, I will find it and zip it up and get it into sandbox here or something but give me a day or so....

    but when you look at that blog post and see that it's just one pixel shader f() that does the thing!

    basicly he creates a large texture / surface to be "shaded"
    so the hardware on the GPU will call that f() for each pixel of the texture. 

    so the normal "loop to iterate over the bitmap" logic has been done for us by the GPU hardware, now all you have to do is figure out the "escape" value and transalate that to a color value.

    when I find my code I have a color pallet I pass in that replaces the gray-scale with colors.

    I'll post back here after I find the code.

  • User profile image
    longnight

    I’m curios here, I have a lot of fun playing with the Bitmap image buffer in managed C++, but I haven’t found a good way to do this using C#. Can you shed some light on how you’re accessing the image buffer in C#?

  • User profile image
    longnight

    Sure, but when working in the unsafe arena I tend to prefer working in c++.

    Working with 32bpp shouldn't be a big deal, just change your byte[] to a int[]. But I agree that recopying the whole buffer for every frame is probably what’s slowing you down.

  • User profile image
    evildictait​or

    RoyalSchrubber wrote:
    
    (dunno if you know this - c# can use pointers just like c and c++


    Well, er... sort of. You have to bear in mind that in C# there are multiple "types" of pointer, such as managed pointers and unsafe handles, whereas in C everything is either a void* or some compiler-abstraction of a void*.

    Basically you can use C# to meddle with pointers, but if you do so you need to be careful because Bad ThingsTM can happen if you don't know what you're doing (such as the GC moves your memory blob).

  • User profile image
    figuerres

    Hey I started working on my XNA mandelbrot code to bring  it uptodate with XNA Game Studio 2 and found some more code that could be fun to update:

    http://blogs.msdn.com/manders/archive/2006/11/28/wendybrot-1-1-faster-more-support-cleaner-code.aspx

    this looks like it also uses a pixel shader to render the bitmap.

    another day or so and I think I will be ready to post my code.

    then I guess I will see if I can update the "Wendybrot" to GS V2
    and ask the author about posting it online.

Comments closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.