Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nightly Build Crashes During Render of Complicated Object #5069

Open
LenStruttmann opened this issue Mar 25, 2024 · 15 comments
Open

Nightly Build Crashes During Render of Complicated Object #5069

LenStruttmann opened this issue Mar 25, 2024 · 15 comments

Comments

@LenStruttmann
Copy link

LenStruttmann commented Mar 25, 2024

OpenSCAD nightly build OpenSCAD-2024.03.23-x86-64 with Manifold consistently crashes while attempting to render (F6) the attached complicated model after about 15 minutes.

To Reproduce
Attempt to render (F6) the attached model.

Expected behavior
Successful render or a graceful failure.

Code reproducing the issue

r1 = 10;
r2 = 5;
halfSide = 1;

faces = [
  [ 0, 4, 1],
  [ 3, 4, 0],
  [ 2, 4, 3],
  [ 1, 4, 2],
  [ 0, 1, 2, 3],
];


union()
{
  sphere(r1);
  for (phi=[0:1:180], theta=[0:1:360])
  {
    points = [ 
      [-halfSide, -halfSide, 0],
      [ halfSide, -halfSide, 0],
      [ halfSide,  halfSide, 0],
      [-halfSide,  halfSide, 0],
      [ 0, 0, r1 + rands(0,10,1)[0] ],
    ];

    rotate( [0, phi, theta]) 
    polyhedron(points = points, faces = faces);
  }
}

Environment and Version info (please complete the following information):
OS Name Microsoft Windows 11 Home
Version 10.0.22621 Build 22621
System Manufacturer Acer
System Model Predator PH315-54
System Type x64-based PC
Processor 11th Gen Intel(R) Core(TM) i7-11800H @ 2.30GHz, 2304 Mhz, 8 Core(s), 16 Logical Processor(s)
BIOS Version/Date Insyde Corp. V1.12, 6/7/2022
Hardware Abstraction Layer Version = "10.0.22621.2506"
Installed Physical Memory (RAM) 16.0 GB

Library & Graphics card information
OpenSCAD Version: 2024.03.23 (git 0ac066a)
System information: Microsoft Windows 11 (10.0.22621) x86_64 16 CPUs 15.77 GB RAM
User Agent: OpenSCAD/2024.03.23 (git 0ac066a) (Microsoft Windows 11 (10.0.22621) x86_64)
Compiler: GCC "13.2.0" 64bit
MinGW build: MingW64
Debug build: No
Boost version: 1_81
Eigen version: 3.4.0
CGAL version, kernels: 5.5, Cartesian, Extended_cartesian, Epeck
OpenCSG version: OpenCSG 1.5.0
Qt version: 5.15.11
QScintilla version: 2.11.2
InputDrivers:
GLib version: 2.70.2
lodepng version: 20210627
libzip version: 1.5.2
fontconfig version: 2.14.2
freetype version: 2.13.2
harfbuzz version: 7.3.0
cairo version: 1.16.0
lib3mf version: 1.8.1
Features: fast-csg, fast-csg-safer, fast-csg-debug, manifold, roof, input-driver-dbus, lazy-union, vertex-object-renderers-indexing, textmetrics, import-function, predictible-output
Application Path: D:/Downloads/OpenSCAD/OpenSCAD-2024.03.23-x86-64/OpenSCAD-2024.03.23-x86-64
Documents Path: C:\Users\red\Documents
User Documents Path: C:\Users\red\Documents
Resource Path: D:/Downloads/OpenSCAD/OpenSCAD-2024.03.23-x86-64/OpenSCAD-2024.03.23-x86-64
User Library Path: C:/Users/red/Documents/OpenSCAD/libraries
User Config Path: C:\Users\red\AppData\Local/OpenSCAD
Backup Path: C:/Users/red/Documents/OpenSCAD/backups
OPENSCADPATH:
OpenSCAD library path:
C:/Users/red/Documents/OpenSCAD/libraries
D:/Downloads/OpenSCAD/OpenSCAD-2024.03.23-x86-64/OpenSCAD-2024.03.23-x86-64\libraries

OPENSCAD_FONT_PATH:
OpenSCAD font path:
C:/WINDOWS/fonts
C:/Users/red/AppData/Local/Microsoft/Windows/Fonts
C:/Users/red/.local/share/fonts
D:/usr/local/share/fonts
D:/usr/share/fonts
D:/usr/X11/lib/X11/fonts
D:/System/Library/Fonts
D:/Library/Fonts
C:/Users/red/Library/Fonts

GL context creator: WGL (old)
PNG generator: lodepng

GLEW version: 2.1.0
OpenGL Version: 4.6.0 - Build 30.0.101.1273
GL Renderer: Intel(R) UHD Graphics
GL Vendor: Intel
RGBA(8888), depth(24), stencil(8)
GL_ARB_framebuffer_object: yes
GL_EXT_framebuffer_object: yes
GL_EXT_packed_depth_stencil: yes

Additional context
Add any other context about the problem here.

@t-paul
Copy link
Member

t-paul commented Mar 25, 2024

The help output shown does not have Manifold enabled (it would show up with a trailing asterisk manifold*). Can you check the console window output if it says:

Rendering Polygon Mesh using Manifold...

(I've edited the original post for code formatting)

@thehans
Copy link
Member

thehans commented Mar 25, 2024

Having 180*360 points on your spike ball is quite a lot. Testing here, this easily exceeds the RAM on my machine of 16GB.
I suspect the crash is purely due to being out of memory.

Even 180*45 is enough to crash for me. Watching the memory usage with a task monitor i can see it spiking up before the crash.

I don't think there's a bug here unless manifold is possibly using more RAM than expected. (Hard to say what RAM requirements should be for a problem of this magnitude)

@thehans
Copy link
Member

thehans commented Mar 25, 2024

Here is one way to workaround, which I just managed to do:

  • modify the loop in your original script to do partial theta sweep of 36 degrees: theta=[0:1:35]
  • Render and export that (i chose to use 3mf format).
  • use the script below to combine 10 rotations of that and export the result.
union() {
  for(a = [0:36:359]) {
    rotate(a) import("crash_35.3mf");
  }
}

@kintel
Copy link
Member

kintel commented Mar 25, 2024

You don't even have to create a separate file: Just wrap the partial theta sweep in a render() statement, and it will be cached. Using that trick rendered the full model in 2m30s here.

@kintel
Copy link
Member

kintel commented Mar 25, 2024

Anyway, I think we can close this as an expected OOM crash,

Edit: Actually, I think this is a symptom of a real issue, possible related to Manifold caching not being fully implemented (cache object always measure zero bytes). That, combined with pairwise unions, we may be setting ourselves up for unbounded memory allocations.

@kintel
Copy link
Member

kintel commented Mar 26, 2024

@pca006132 I think this may be a good illustration of why we want elalish/manifold#764 to be addressed.

@pca006132
Copy link
Member

another thing is that manifold is not really optimized for memory usage.

@LenStruttmann
Copy link
Author

  1. Yes, I did have MANIFOLD checked. The console message was "Rendering Polygon Mesh using Manifold...". Loaded design 'D:/OpenSCAD/CrashTest.scad'.
    Compiling design (CSG Tree generation)...
    Compiling design (CSG Products generation)...
    Geometries in cache: 47955
    Geometry cache size in bytes: 26893728
    CGAL Polyhedrons in cache: 0
    CGAL cache size in bytes: 0
    Compiling design (CSG Products normalization)...
    Normalized tree has 65342 elements!
    Compile and preview finished.
    Total rendering time: 0:00:06.800

Parsing design (AST generation)...
Compiling design (CSG Tree generation)...
Rendering Polygon Mesh using Manifold...`
2. It does not seem to be an out-of-memory situation. I monitored CPU and memory usage and, while memory usage does peak at about 14GB, memory usage was at about 10GB when it crashed.
3. Rendering on OpenSCAD 2021.01 was successful, although it does take 9 hours to complete.
4. I'm not really looking for alternative methods of creating this object. I was just playing around and discovered a stress test that caused OpenSCAD to crash. My rational for submitting this as a bug is that a graceful failure is preferred over a crash.

@pca006132
Copy link
Member

Interesting, maybe someone can use gdb to see what is causing it to crash?

@pca006132
Copy link
Member

I am not entirely sure why it crashes for you on windows, but it is definitely running out of memory for me on Linux.
And I think in general it is hard to avoid crashing due to using too much memory. Modern operating systems over-commit memories, so you will not notice allocation failures. In fact, when the memory is freshly allocated, they are not yet paged in, so you are usually using less memory than what you asked for. The operating system OOM-killer will just kill your process when it is giving too much pressure to the system.

I think maybe in your case it is already paging out, and the OOM killer decided it is using too much memory and kills it.

@kintel
Copy link
Member

kintel commented Mar 27, 2024

To help illustrate where I think all the memory goes:

  • In this case, OpenCAD is given a very long flat list of PolySet objects and is asked to union them
  • OpenSCAD will then convert each of the PolySets to a Manifold object
  • ..and proceed to build an unbalanced binary tree of unions, each union being a new Manifold node representing the tree built so far
  • Each Manifold object in this process will be stored in our internal cache, subject to cache size limitations. Since Manifold objects are reported as zero size, the cache grows unbounded
  • Even after (if) finishing the rendering, the cache will keep growing until OpenSCAD exits.

FYI: I'm working on optimizing the binary tree building part of this (exploring Manifold's batch mechanism), but the unbounded cache still needs addressing.

@pca006132
Copy link
Member

In addition, the cache will make manifold unable to flatten the tree internally because it thinks that the node may be reused in a different part. This is why I said caching may cause performance issues and we probably want a better cache policy.

@kintel
Copy link
Member

kintel commented Mar 27, 2024

Right, as a start we probably shouldn't cache nodes that are not actual OpenSCAD nodes (like intermediate nodes in a binary tree described above).

@pca006132
Copy link
Member

Looking more closely at this, I think this will run OOM even if we disable the cache and remove don't run it in multiple threads, but ideally we should be able to do better than this considering it is not really containing many points.

The problem here is that those spikes often have large AABB, causing the collider to give n^2 pairs, which is bad in terms of memory usage as well as running time. Wonder if there is something we can do here @elalish. Maybe we can have a fallback to boolean3 that process each collision pair one by one without getting the full collision array when there are too many collision pairs? Probably need to change quite a lot of stuff though.

@elalish
Copy link

elalish commented Apr 1, 2024

If the total number of intersections isn't huge, but the potential intersections is, then boolean_result.cpp shouldn't need any changes, but boolean3.cpp will. Basically we'd need to run those collisions in batches. The algorithm starts with the potential high-level overlaps, then figures out all the lower level constructs it needs to evaluate, then builds those back up to the real high-level overlaps. That system should still work with batching, but yes, it'll be a fair bit of code change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants