POV-Ray : Newsgroups : povray.off-topic : Euclidean infinite detail : Re: Euclidean infinite detail Server Time
1 Jul 2024 01:33:02 EDT (-0400)
  Re: Euclidean infinite detail  
From: clipka
Date: 29 Oct 2016 02:08:16
Message: <58143cd0$1@news.povray.org>
Am 28.10.2016 um 18:44 schrieb Bald Eagle:

> I know we've touched on this topic, and you've even trimmed down the memory
> footprint of the spheres - can you give me a better idea of the memory
> difference?  I thought you had previously said there wasn't much of one, but
> perhaps I misunderstood exactly what you were saying.
> 
> I guess I just have trouble seeing how this
> 
>   blob {
>     threshold 0.6
>       sphere { <.75, 0, 0>, 1, 1 }
>       sphere { <-.375, .64952, 0>, 1, 1 }
>       sphere { <-.375, -.64952, 0>, 1, 1 }
>     }
> 
> uses less memory than
> 
>       sphere { <.75, 0, 0>, 1 }
>       sphere { <-.375, .64952, 0>, 1 }
>       sphere { <-.375, -.64952, 0>, 1 }

Each primitive has the following fields (data sizes given for 64-bit
Windows; data consumption may vary depending on operating system and/or
CPU architecture):

    - a pointer to the VMT(*) (8 bytes)
    - a type field (4 bytes)
    - a pointer to a texture (8 bytes overhead)
    - a pointer to an interior texture (8 bytes overhead)
    - a shared pointer to an interior (16 bytes overhead)
    - a list of bounded_by objects (32 bytes overhead)
    - a list of clipped_by objects (32 bytes overhead)
    - a list of light_group objects (32 bytes overhead)
    - a bounding box (24 bytes)
    - a pointer to a transformation matrix (8 bytes overhead)
    - a photons density field (4 bytes)
    - a radiosity importance setting (16 bytes)
    - a set of various flags (4 bytes)

(*VMT = Virtual Method Table, an artifact of many object-oriented
language implementations, serving to support a feature called polymorphism.)

Including a few more bytes of padding to satisfy data type alignment
constraints, this currently adds up to 208 bytes on a Windows machine.

Most of the pointers and lists will be left empty in your examples, so
will "only" occupy the aforementioned overhead; a notable exception is
the texture: Each and every primitive will reference a texture, and for
technical reasons it will have its own personal copy thereof (I'm still
seeking for a sane way to avoid this memory hog). Even if you do not
explicitly specify a texture, it will be a copy of the default texture,
and weigh in at 112 bytes (minimum) on a Windows machine.

Another notable exception is the interior, which whill be forced to a
"neutral" interior data block if not explicitly specified. Such a
neutral interior weighs in at another 96 bytes.

Add to that the sphere-specific data:

    - a center (24 bytes)
    - a radius (8 bytes)
    - an additional flag (1 byte)

With some more padding for data type alignment, this weighs in at
another 40 bytes of data.

Another 8 bytes are required for a pointer to actually hook the sphere
up into the scene, and another 40 bytes worth of data required to
represent it in the scene-level bounding hierarchy.

So for each and every full-fledged sphere, we start with a baseline of a
whopping 504 bytes worth of data.


Compare that to the requirements for a blob element(*):

    - a type field (2 bytes)
    - an index field (4 bytes)
    - an origin vector (24 bytes)
    - a cylinder length field (8 bytes)
    - a squared-radius field (8 bytes)
    - a triplet of coefficients (24 bytes)
    - a pointer to a texture (8 bytes overhead)
    - a pointer to a transformation matrix (8 bytes overhead)

Again including a few more bytes of alignment padding, this adds up to
just 88 bytes.

It is important to note that in contrast to primitives, no texture data
block is created for blob elements unless a texture is explicitly
specified, so we're only stuck with the pointer overhead.

Another 8 bytes are required for a pointer to actually hook the element
up into the blob, and another 48 bytes worth of data required to
represent it in the blob's internal bounding hierarchy.

Additional memory is required at run-time for temporary data, but this
is difficult to quantify since on one hand the corresponding data
structure is shared among all blobs, while on the other hand a separate
copy of the data structure is required for each thread. Effectively, the
largest blob in the scene requires another 104 bytes per blob element
per thread.

So if you have just one single blob in your scene, each of that blob's
elements weighs in at 144 bytes, plus 104 bytes per thread.

(*NB these are internal elements; each spherical element corresponds to
one of these, while each cylindrical element actually requires three of
these: One for the cylindrical portion, and two more for the
hemispherical end portions.)


If it wasn't for the temporary data structure, this would boil down to:

    (A) 504 bytes per genuine sphere, vs.
    (B) 144 bytes per spherical blob element.

If you use the naive approach of shoving all your spherical blob
elements into one large blob primitive, that advantage is quickly eaten
up on multi-core systems, and completely lost at 4 or more threads (an
effect I hadn't considered previously); however, presuming the goal is
indeed to get spheres rather than blobby things, the total cost can be
minimized by splitting up your N blob elements among C*sqrt(N) blob
primitives (with C being a constant depending on the number of threads),
in which case the per-thread cost becomes negligible for large N.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.