Problem
libcuopt.so is currently ~90 MB in a local development build (3 architectures). A CI release build targets 6–8 CUDA architectures and the binary reaches ~250–300 MB based on the per-arch fatbin growth rate observed below. This creates friction for:
Measured breakdown (local build, sm_30/70/75)
| Section |
Size |
.nv_fatbin (CUDA fatbin) |
60.6 MB |
| Text + rodata (CPU code) |
~18 MB |
| Exported dynamic symbols |
11 601 |
| Global (externally visible) text symbols |
1 046 |
Dynamic NEEDED entries |
27 |
The fatbin is 67 % of the binary and grows linearly with each added CUDA architecture.
Opportunities
1. CUDA fatbin (biggest lever, ~60 %+ of binary)
- The local build includes sm_30 (Kepler), which has been EOL since CUDA 12 and should be removed from the supported-arch list.
- For release builds the RAPIDS preset adds sm_70/75/80/86/89/90 — each architecture adds ~10–15 MB. Defining a cuOpt-specific minimum supported arch (e.g. sm_70 / Volta) and removing architectures below it would shrink the fatbin proportionally.
- Alternatively, ship one PTX image (for forward-compat) plus only the real
.cubin for currently-released GPU families, dropping cubin entries for archs that share the same code path.
2. Symbol visibility
libcuopt.so currently exports 1 046 global text symbols with no project-wide -fvisibility=hidden flag set in cpp/CMakeLists.txt. Many of these are C++ internal symbols that users should not call directly; only the stable C API surface (declared in include/cuopt/) needs to be exported.
Recommended changes:
set_target_properties(cuopt PROPERTIES
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
)
Plus an export-map / version script that explicitly lists only the cuopt_* C API symbols, so internal C++ templates, helper classes, and third-party headers inlined into the translation units are not exported. This also speeds up dlopen and reduces symbol-table size.
3. Dynamic dependency count (27 NEEDED entries)
This overlaps with #1203 (static-link gRPC/protobuf/abseil/TBB/libgomp). Reducing external dynamic dependencies also reduces the runtime footprint of the loaded image.
4. Debug info in development builds
Confirm release/package builds use -g0 (no debug info). A -g2 slip doubles the binary size; currently the dev build is 90 MB unstripped vs 80 MB fully stripped, suggesting minimal DWARF is embedded, but this should be explicitly enforced in the CI packaging CMake preset.
Expected outcome
| Change |
Estimated savings |
| Drop sm_30 (Kepler, EOL) |
~10–12 MB |
| Drop below-Volta archs in release |
~10–20 MB (depends on arch count) |
-fvisibility=hidden + export map |
~5–10 MB (smaller symbol tables, better dead-code elim) |
| Static-link gRPC/protobuf/abseil + strip (see #1203) |
reduces NEEDED count; net size depends on what is stripped |
Targeting a release binary under 200 MB for a full-arch build appears achievable without removing any current functionality.
Related
Problem
libcuopt.sois currently ~90 MB in a local development build (3 architectures). A CI release build targets 6–8 CUDA architectures and the binary reaches ~250–300 MB based on the per-arch fatbin growth rate observed below. This creates friction for:.soMeasured breakdown (local build, sm_30/70/75)
.nv_fatbin(CUDA fatbin)NEEDEDentriesThe fatbin is 67 % of the binary and grows linearly with each added CUDA architecture.
Opportunities
1. CUDA fatbin (biggest lever, ~60 %+ of binary)
.cubinfor currently-released GPU families, dropping cubin entries for archs that share the same code path.2. Symbol visibility
libcuopt.socurrently exports 1 046 global text symbols with no project-wide-fvisibility=hiddenflag set incpp/CMakeLists.txt. Many of these are C++ internal symbols that users should not call directly; only the stable C API surface (declared ininclude/cuopt/) needs to be exported.Recommended changes:
Plus an export-map / version script that explicitly lists only the
cuopt_*C API symbols, so internal C++ templates, helper classes, and third-party headers inlined into the translation units are not exported. This also speeds updlopenand reduces symbol-table size.3. Dynamic dependency count (27
NEEDEDentries)This overlaps with #1203 (static-link gRPC/protobuf/abseil/TBB/libgomp). Reducing external dynamic dependencies also reduces the runtime footprint of the loaded image.
4. Debug info in development builds
Confirm release/package builds use
-g0(no debug info). A-g2slip doubles the binary size; currently the dev build is 90 MB unstripped vs 80 MB fully stripped, suggesting minimal DWARF is embedded, but this should be explicitly enforced in the CI packaging CMake preset.Expected outcome
-fvisibility=hidden+ export mapNEEDEDcount; net size depends on what is strippedTargeting a release binary under 200 MB for a full-arch build appears achievable without removing any current functionality.
Related