Image Map Image Map
Page 2 of 6 FirstFirst 123456 LastLast
Results 11 to 20 of 52

Thread: Wanted: 8086 mandelbrot generator?

  1. #11

    Default

    Good point. I always just called them video cards. Would that be correct? "GPU" didn't come into my vocabulary until the last 10 years maybe.

    On an unrelated note, do these Mandelbrot generators use the coprocessor? I recently installed an 8087 in my PS/2 Model 30, and I'm itching find a program to show off it's massive floating-point processing POWER!! (sarcastic caps and exclamations)

    Quote Originally Posted by Scali View Post
    Small nitpick here:
    I often see the term 'GPU' these days to indicate any kind of video chip and/or board.
    This is not correct. CGA, EGA, VGA and related technologies do not quality as a GPU, since they are not processing units. They are merely logic arrays that can be controlled by the CPU, but they cannot perform any functions independently, let alone a sequence of functions. CGA does not even have any arithmetic capabilities at all. EGA and VGA have a very basic ALU that can only perform an action when the CPU issues a read or write of a VRAM address.
    The first common GPU was the NVIDIA GeForce. What made it a GPU is that it actually is a standalone processing unit, much like a CPU. That is, you can place a series of commands in its video memory (a 'program'), and the GPU will execute these completely independently to generate an image on screen.
    In fact, GPU was NVIDIA's marketing term. When ATi launched its competitor, they used the term VPU: Visual Processing Unit. It never caught on though.
    https://www.nvidia.com/page/geforce256.html
    NV's definition is very strict, and requires full 3D processing and a minimum performance guideline.

    (Although one could probably argue that certain older display adapters, such as the IBM PGC, or perhaps the Amiga with its copper/blitter combination, would also qualify to some extent. However, the term 'GPU' was not coined yet, so they were never referred to as such, so it would be an anachronism to do so).

  2. #12
    Join Date
    Feb 2017
    Location
    Zürich, Switzerland
    Posts
    63

    Default

    The one I just hacked together (based heavily on someone else's code) uses 8.8 fixed point integer arithmetic. Which means it's probably more of a blindfolded stab in the dark in the vague direction of something mandelbrottish than actually drawing a true image.

    My 5140 doesn't have an FPU, and I haven't taken the lid off to see whether there's a socket for one. (I don't even know if the 8088 supported one.) Anyone know?

  3. #13

    Default

    Is it written in FORTRAN. If not it isn't interesting

  4. #14
    Join Date
    Jan 2007
    Location
    Pacific Northwest, USA
    Posts
    27,647
    Blog Entries
    20

    Default

    Quote Originally Posted by hjalfi View Post
    My 5140 doesn't have an FPU, and I haven't taken the lid off to see whether there's a socket for one. (I don't even know if the 8088 supported one.) Anyone know?
    Do you mean, like, the 8087? (Intel called it an NDP for "Numeric Data Processor")

  5. #15

    Default

    Quote Originally Posted by hjalfi View Post
    The one I just hacked together (based heavily on someone else's code) uses 8.8 fixed point integer arithmetic. Which means it's probably more of a blindfolded stab in the dark in the vague direction of something mandelbrottish than actually drawing a true image.
    I'd be interested to see the code (and the output). Off the top of my head, I seem to recall that Fractint's 16-bit high-speed Mandelbrot code uses 2.14 fixed point and was only good for 1 or 2 zooms before it had to switch to 32-bit. So 8 fractional bits seems like it might not be enough (although avoiding shifts might be a big speed win).

    Quote Originally Posted by hjalfi View Post
    My 5140 doesn't have an FPU, and I haven't taken the lid off to see whether there's a socket for one. (I don't even know if the 8088 supported one.) Anyone know?
    The 8088 does support one (the 5160 has a socket for it). It's a lot faster than the CPU for floating point arithmetic, but still slower than fixed point IIRC.

  6. #16
    Join Date
    Feb 2017
    Location
    Zürich, Switzerland
    Posts
    63

    Default

    Re the Mandelbrot code: I can't show you my version because the original author didn't put a license on their code (important tip: ALWAYS PUT LICENSES ON YOUR CODE), which means I can't distribute mine. But I can point you at theirs, which is http://blog.nothinguntoward.eu/?p=38. There's a nice writeup. (Actually it's using 9.7 fixed-point arithmetic. I hadn't noticed that the first time round.)

    I changed it to colour mode, replaced the 80186 instructions with 8086 ones, and converted it from a booter into a .com file --- all pretty trivial (although working round the 8086 imul instruction's register requirements was painful; the original manages to keep all working state in registers by using every single one of them, so there's not much room to work with).

    Taking another look at the code, the iteration count is really high --- 256. Reducing it to 32 makes no observable difference to the image and it's much faster. Also using iterations%3+1 for the colour rather than iterations&3 makes for a much more pleasing image, although now I notice that there's a big artifact on the left due to the fixed point arithmetic overflowing:

    grab.jpg

    AFAICT the 5140 doesn't have a socket for a maths coprocessor. Oh, well.

  7. #17

    Default

    Quote Originally Posted by hjalfi View Post
    Taking another look at the code, the iteration count is really high --- 256. Reducing it to 32 makes no observable difference to the image and it's much faster. Also using iterations%3+1 for the colour rather than iterations&3 makes for a much more pleasing image, although now I notice that there's a big artifact on the left due to the fixed point arithmetic overflowing:
    That's not too bad at all! I think the artefact on the left may not actually be due to fixed point arithmetic overflowing at all, but due to using the wrong bailout condition. It looks like you're bailing out if |z|>1 but there are some points in the set outside this range, such as z=-2, so you need to bail out if |z|>2. Although, I think the image looks nicer using |z|>4 if there's enough precision (and using 9.7, there should be). Using 4 instead of 2 prevents all the contours piling up at z=-2.

  8. #18
    Join Date
    Feb 2017
    Location
    Zürich, Switzerland
    Posts
    63

    Default

    It tests for bail-out by checking for overflow in the multiplies. (That bit's not my code!)

    The article suggests that this works because their values are scaled such that if either of the multiplies overflows this indicates that the resulting point must be outside the |z|>2 circle and therefore will bail out. 9.7 fixed point can represent n^2 where n is -2..2 before overflowing, so that does seem reasonable; but I still get the feeling there's something not quite right with the author's logic...

    I also notice that using 9.7 fixed point allows the 16-bit integer pixel value (-160..160, -100..100) to be loaded directly into the fixed point c registers, resulting in (-1.25..1.25, -0.78..0.7, which is a neat trick. No scaling needed.

    I should rewrite it from scratch, really, so that I understand what's actually happening.

    Re optimisations: I know there's a toolbox of easy tricks to make rendering Mandelbrots cheaper... things like identifying bounded areas which you know are all the same colour, and so can be filled in a single operation without needing to render the contents. But these are out of fashion these days given the speed of modern computers, and I can't find any references.

  9. #19

    Default

    Quote Originally Posted by hjalfi View Post
    It tests for bail-out by checking for overflow in the multiplies. (That bit's not my code!)
    Ah, so it does. Looks like the bailout condition is either |x*x-y*y| >= 4 or |x*y| >= 4 which is responsible for the strange pattern. Actually I'm not completely sure of the conditions under which the overflow flag is set after an IMUL - I had thought it was "if the result doesn't fit into a signed 16-bit integer" but looking at Intel documentation it actually seems like only results <=-0x10000 or >=0x10000 set the overflow flag. I will check what my 8088 does shortly...

    Quote Originally Posted by hjalfi View Post
    I also notice that using 9.7 fixed point allows the 16-bit integer pixel value (-160..160, -100..100) to be loaded directly into the fixed point c registers, resulting in (-1.25..1.25, -0.78..0.7, which is a neat trick. No scaling needed.
    Indeed it is! And that makes a lot of sense when optimizing for size. If you're optimizing for speed and want a little more accuracy then scaling can be done trivially fast (just add a constant instead of incrementing).

    Quote Originally Posted by hjalfi View Post
    Re optimisations: I know there's a toolbox of easy tricks to make rendering Mandelbrots cheaper... things like identifying bounded areas which you know are all the same colour, and so can be filled in a single operation without needing to render the contents. But these are out of fashion these days given the speed of modern computers, and I can't find any references.
    One pretty easy thing to do is check if you're in the main cardioid or the largest circle - the equations for these can be found here. As these points always hit the iteration limit, finding them early can give a big speedup.

    I have to admit I've been totally nerd-sniped by this today. I've figured out an algorithm for computing a Mandelbrot iteration with just 3 table lookups and some additions and subtractions. It doesn't use the multiply instructions at all so should be quite a bit faster than Fractint's code on an 8088/8086 if it works. I also have an idea for a nice (and simple) solid-guessing algorithm (which may or may not be similar to Fractint's one, which I never quite managed to understand completely).

  10. #20

    Default

    Quote Originally Posted by reenigne View Post
    Actually I'm not completely sure of the conditions under which the overflow flag is set after an IMUL - I had thought it was "if the result doesn't fit into a signed 16-bit integer" but looking at Intel documentation it actually seems like only results <=-0x10000 or >=0x10000 set the overflow flag. I will check what my 8088 does shortly...
    Okay, seems I was looking at an outdated and buggy version of the Intel docs (from the Pentium 4 era). Current documentation says that the overflow flag is set if the result doesn't fit into a signed 16-bit integer and my 8088 behaves this way as well. That means that the bailout condition is "|x*x-y*y| >= 2 or |x*y| >= 2". So for example on the real axis the points in the range -2 to -sqrt(2) (which are all in the Mandelbrot set) will trigger the bailout condition. So yes, it seems that the original program is buggy here.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •