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

mesh_make_atlas performance degrades with larger meshes on iOS build #191

Open
Volutionn opened this issue Nov 16, 2024 · 4 comments
Open

Comments

@Volutionn
Copy link

Hi, I'm encountering a performance issue with mesh_make_atlas when using Geogram on iOS. The function works fine for small meshes, but I'm experiencing a severe slowdown with larger meshes. The issue seems to occur when the vertex count exceeds ~16,000 (tested on a simple plane by progressively subdividing it).

Do you have any ideas about what might be causing this performance degradation with larger meshes? Are there any optimizations or settings I should consider to handle larger meshes efficiently?

Additionally, I'm getting this warning: Warning: Could not initialize SuperLU extension when trying to use ABF++, which causes it to fall back to LSCM. Do you know if I should be able to make SuperLU work on iOS?

Thank you!

@BrunoLevy
Copy link
Owner

Hello,

I do not have much experience with iOS. On which platform are you running iOS ? Is it a phone ? Did you compare the performance with the same code running on a computer ?

Can you share a small program + data so that I can check ?

About SuperLU, you have several ways to make it work:

  • compile SuperLU separately, and install it in the same directory as geogram, then the dynamic linker code in geogram/NL/nl_superlu.c will (hopefully) find it. You may need to modify things in NL/nl_os.c for opening dynamic libraries and finding symbols in them (not sure the code there works with iOS)
  • or compile third_party/numerics (that bundles SuperLU). (note: works also with the dynamic linker in nl_os.c)

@Volutionn
Copy link
Author

Volutionn commented Nov 18, 2024

Thank you for your help!

I assumed it was an issue with my custom build for iOS, but I just tried the macOS build (M1) and encountered issues there as well.

Here are the 2 .obj I used for my test: Planes_OBJ.zip

Test 1

For the first test, I used the ./bin/opennl_LSCM example application.

Plane_15K.obj

Loaded 14762 vertices and 29040 facets
Solving ...
Solver time: 1.26
Used iterations: 2667

Plane_16K.obj

Loaded 16248 vertices and 31994 facets
Solving ...
Solver time: 0
Used iterations: 0

Observations:

Both .obj files were successfully generated and appeared correct.
However, the logs are inconsistent, which might help pinpoint the underlying issue.

Test 2

For the second test, I used the following custom code to parameterize the same meshes using the mesh_make_atlas function.

#include <geogram/mesh/mesh.h>
#include <geogram/mesh/mesh_io.h>
#include <geogram/parameterization/mesh_atlas_maker.h>
#include <geogram/basic/logger.h>

int main(int argc, char** argv) {
    if (argc != 3) {
        GEO::Logger::err("Test") << "Usage: " << argv[0] << " input_mesh output_mesh" << std::endl;
        return 1;
    }

    GEO::initialize();

    GEO::Mesh mesh;
    if (!GEO::mesh_load(argv[1], mesh)) {
        GEO::Logger::err("Test") << "Failed to load mesh: " << argv[1] << std::endl;
        return 1;
    }

    GEO::mesh_make_atlas(mesh);

    if (!GEO::mesh_save(mesh, argv[2])) {
        GEO::Logger::err("Test") << "Failed to save mesh: " << argv[2] << std::endl;
        return 1;
    }

    GEO::Logger::out("Test") << "Atlas generation completed successfully." << std::endl;
    return 0;
}

Results:

  • Plane_15K.obj ran successfully, generating a valid .obj file.
  • Plane_16K.obj failed with the following assertion:
Assertion failed: variable_exists.
File: /geogram/src/lib/geogram/basic/environment.cpp,
Line: 217
Stacktrace: 0   libgeogram.1.9.1-rc.dylib           0x0000000100f772e4 _ZN3GEO7Process20os_print_stack_traceEv + 44
Stacktrace: 1   libgeogram.1.9.1-rc.dylib           0x0000000100f33ef4 _ZN3GEO20geo_assertion_failedERKNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEES8_i + 528
Stacktrace: 2   libgeogram.1.9.1-rc.dylib           0x0000000100f5bc30 _ZNK3GEO11Environment9get_valueERKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE + 476
Stacktrace: 3   libgeogram.1.9.1-rc.dylib           0x00000001010b7804 _ZN3GEO8Delaunay6createEhRKNSt3__112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE + 216
Stacktrace: 4   libgeogram.1.9.1-rc.dylib           0x00000001010d7cb4 _ZN3GEO28CentroidalVoronoiTesselationC2EPNS_4MeshEhRKNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE + 212
Stacktrace: 5   libgeogram.1.9.1-rc.dylib           0x0000000101304750 _ZN3GEO12mesh_segmentERNS_4MeshENS_13MeshSegmenterEjb + 684
Stacktrace: 6   libgeogram.1.9.1-rc.dylib           0x00000001012f1680 _ZN3GEO15mesh_make_atlasERNS_4MeshEdNS_18ChartParameterizerENS_11ChartPackerEb + 1828
Stacktrace: 7   test_mesh_make_atlas                0x0000000100412dd0 main + 584
Stacktrace: 8   dyld                                0x000000019d2120e0 start + 2360
libc++abi: terminating due to uncaught exception of type std::runtime_error: Assertion failed: variable_exists.
File: /geogram/src/lib/geogram/basic/environment.cpp,
Line: 217
zsh: abort

Considering that the issue is also on macOS it's probably not relevant anymore, but I'm running it on an iPhone. The time differences range from under a second at 15K vertices to a few minutes when the number exceeds roughly 16K.
From my observations, with 15K vertices the unwrap is correct, but at 16K it seems to never converge and ends up creating an island per face.


Thank you for the info regarding SuperLU ! I'll look into it further and give it another shot to make it work

@BrunoLevy
Copy link
Owner

BrunoLevy commented Nov 20, 2024

Hello,
geogram needs some setup and initialization to operate properly, as follows:

#include <geogram/mesh/mesh.h>
#include <geogram/mesh/mesh_io.h>
#include <geogram/parameterization/mesh_atlas_maker.h>
#include <geogram/basic/logger.h>
#include <geogram/basic/command_line.h>
#include <geogram/basic/command_line_args.h>

int main(int argc, char** argv) {
    GEO::initialize();  // this line should be first
    GEO::CmdLine::import_arg_group("standard"); // declare some command line arg
    GEO::CmdLine::import_arg_group("algo");  // with their default values, used by the solver

    std::vector<std::string> files; // the two filenames on the command line

    // set all command arguments, and get the two filenames 
    // (you can change the behavior of some algorithms in geogram
    // using command line argument, use "myprogram -h" to see what can be done.
    if(!GEO::CmdLine::parse(argc, argv, files, "inputfile outputfile")) {  
	exit(-1);
    }

    GEO::Mesh mesh;
    if (!GEO::mesh_load(files[0], mesh)) {
        GEO::Logger::err("Test") << "Failed to load mesh: "
				 << files[0] << std::endl;
        return 1;
    }

    GEO::mesh_make_atlas(mesh);

    if (!GEO::mesh_save(mesh, files[1])) {
        GEO::Logger::err("Test") << "Failed to save mesh: " << files[1]
				 << std::endl;
        return 1;
    }

    GEO::Logger::out("Test")
	<< "Atlas generation completed successfully." << std::endl;
    return 0;
}

@Volutionn
Copy link
Author

Hello @BrunoLevy and thank you for your time!

I overly simplified my test code and indeed missed some of those initialization steps, but in my iOS implementation, I already had these lines. This explains why my demo code resulted in an assertion error (only when using the 16K plane for some reason), while my iOS implementation was running.

However, I can't figure out why there's this significant change in behavior at 16K vertices. Is this expected behavior?

On my Mac, going from ~15K to ~16K vertices caused the processing time to increase from 0.296s to 0.816s. It also resulted in 4 charts instead of 1, even though it’s just a basic plane with more subdivisions.

What I find also intriguing is the behavior in the example application opennl_LSCM. It goes from 2,667 iterations to presumably no iterations at all (based on the output log), despite the input being a heavier mesh.

Please let me know how I can contribute in any other way that might help debug or understand this behavior. I’d be happy to provide any additional details or share more about my setup if needed!

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

No branches or pull requests

2 participants