Skip to content

QVAC-17129 feat: add dynamic backend loading to nmtcpp GGML backend for GPU acceleration#1617

Merged
iancris merged 9 commits into
mainfrom
feat/QVAC-17129-add-dynamic-backend-loading-nmtcpp
Apr 22, 2026
Merged

QVAC-17129 feat: add dynamic backend loading to nmtcpp GGML backend for GPU acceleration#1617
iancris merged 9 commits into
mainfrom
feat/QVAC-17129-add-dynamic-backend-loading-nmtcpp

Conversation

@iancris

@iancris iancris commented Apr 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add dynamic GGML backend loading to the NMT addon so GPU backend plugins (OpenCL, Vulkan) are discovered at runtime
  • Follow the established LLM addon pattern (LlamaLazyInitializeBackend) with a new NmtLazyInitializeBackend singleton
  • Support backendsDir config param for Android APK lib path and openclCacheDir for OpenCL kernel cache
  • Install GPU backend .so plugins to prebuilds via GGML_AVAILABLE_BACKENDS CMake loop

Changes

New files

  • addon/src/model-interface/NmtLazyInitializeBackend.hpp — Lazy-init singleton with RAII NmtBackendsHandle
  • addon/src/model-interface/NmtLazyInitializeBackend.cpp — Implementation: ggml_backend_load_all_from_path(), OpenCL cache dir, ref-counted lifecycle
  • addon/tests/test_nmt_lazy_init_backend.cpp — 15 GoogleTest unit tests

Modified files

  • TranslationModel.hpp/cpp — Extract backendsdir/openclcachedir from config in load(), init handle before nmt_init_from_file_with_params()
  • PivotTranslationModel.hpp/cpp — Init backends handle in constructor before sub-model load()
  • index.js — Default backendsDir to prebuilds path
  • CMakeLists.txt — Add BACKENDS_SUBDIR, BACKEND_DL_LIBS loop, new source file

Test plan

  • bare-make generate, build, install pass locally
  • 15 new C++ unit tests pass (NmtLazyInitializeBackend singleton, ref-counting, RAII handle, move semantics)
  • cpp-tests CI pass
  • cpp-lint CI pass (clang-format + clang-tidy clean)
  • All 9 prebuilds pass (linux-x64, linux-arm64, darwin-arm64, darwin-x64, ios-arm64, ios-arm64-simulator, ios-x64-simulator, win32-x64, android-arm64)
  • All integration tests pass (darwin-arm64, linux-x64, linux-arm64, win32-x64)
  • Mobile E2E tests pass (iOS, Android)

CI: https://github.com/tetherto/qvac/actions/runs/24501619382

Asana

https://app.asana.com/0/1212638335655990/1214055988275114

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          47                 0   100.00%           7                 0   100.00%          67                 0   100.00%          24                 2    91.67%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 162                49    69.75%          23                 3    86.96%         326                65    80.06%          66                32    51.52%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         135                28    79.26%          38                12    68.42%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          74                17    77.03%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         541               161    70.24%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          36                15    58.33%
nmt_loader.cpp                       283                80    71.73%          14                 0   100.00%         786               109    86.13%         148                71    52.03%
nmt_state_backend.cpp                199                53    73.37%          20                 0   100.00%         431                86    80.05%         122                53    56.56%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          58                25    56.90%
nmt_utils.cpp                         24                 4    83.33%           3                 0   100.00%          36                 5    86.11%          16                 7    56.25%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1263               349    72.37%         125                16    87.20%        3034               559    81.58%         722               303    58.03%

1 similar comment
@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          47                 0   100.00%           7                 0   100.00%          67                 0   100.00%          24                 2    91.67%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 162                49    69.75%          23                 3    86.96%         326                65    80.06%          66                32    51.52%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         135                28    79.26%          38                12    68.42%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          74                17    77.03%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         541               161    70.24%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          36                15    58.33%
nmt_loader.cpp                       283                80    71.73%          14                 0   100.00%         786               109    86.13%         148                71    52.03%
nmt_state_backend.cpp                199                53    73.37%          20                 0   100.00%         431                86    80.05%         122                53    56.56%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          58                25    56.90%
nmt_utils.cpp                         24                 4    83.33%           3                 0   100.00%          36                 5    86.11%          16                 7    56.25%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1263               349    72.37%         125                16    87.20%        3034               559    81.58%         722               303    58.03%

iancris and others added 7 commits April 17, 2026 13:02
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bare runtime does not have Node.js built-in 'path' module.
All other files in the package use 'bare-path'.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lationModel

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…extraction

Stop erasing backendsdir/openclcachedir from config_ in TranslationModel::load
so reload() re-initializes the backend with the original path instead of
falling back to the default loader. Without this, GPU backends disappeared
silently after any model reload on Android.

Use std::get_if<std::string> for backendsdir/openclcachedir extraction in
TranslationModel and PivotTranslationModel; on type mismatch log a warning
and fall through instead of propagating bad_variant_access out of the load
path.

Default backendsDir in JS only when the field is missing (=== undefined)
rather than on any falsy value, so callers passing "" to force the default
system backend loader are respected.

Refs QVAC-17129.
PivotTranslationModel only uses Bergamot — GGML dynamic backend loading
is for the IndicTrans (GGML) path, which is a different inference engine.
The earlier backendsHandle_ initialization in the pivot constructor was
initializing GGML backends even when none were used.

Remove the backend config extraction block, the backendsHandle_ member
and the NmtLazyInitializeBackend include. Sub-model TranslationModel
instances still handle their own backend init on load() for the GGML
path.

Refs QVAC-17129.
@github-actions

Copy link
Copy Markdown
Contributor

✅ E2E Mobile Test Results - iOS

Overall Status: PASSED
Device Farm Result: PASSED
Platform: iOS
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 9a6e8d6

Test Summary

Metric Count
Total Tests 3
✅ Passed 3
❌ Failed 0
⏭️ Skipped 0

Links

  • 🔗 Device Farm Run: View on AWS Device Farm
  • 🔗 Workflow: View Details
  • 📋 Run ARN: arn:aws:devicefarm:us-west-2:833707431398:run:cef7531e-44ed-4ddf-a349-a4b0f72f680d/cbe0062b-0e3d-41ea-9944-2d8cbbc7dfde

Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          47                 0   100.00%           7                 0   100.00%          67                 0   100.00%          24                 2    91.67%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 162                49    69.75%          23                 3    86.96%         326                65    80.06%          66                32    51.52%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         135                28    79.26%          38                12    68.42%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          74                17    77.03%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         541               161    70.24%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          36                15    58.33%
nmt_loader.cpp                       283                80    71.73%          14                 0   100.00%         786               109    86.13%         148                71    52.03%
nmt_state_backend.cpp                199                53    73.37%          20                 0   100.00%         431                86    80.05%         122                53    56.56%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          58                25    56.90%
nmt_utils.cpp                         24                 4    83.33%           3                 0   100.00%          36                 5    86.11%          16                 7    56.25%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1263               349    72.37%         125                16    87.20%        3034               559    81.58%         722               303    58.03%

@github-actions

Copy link
Copy Markdown
Contributor

✅ E2E Mobile Test Results - Android

Overall Status: PASSED
Device Farm Result: PASSED
Platform: Android
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 9a6e8d6

Test Summary

Metric Count
Total Tests 6
✅ Passed 6
❌ Failed 0
⏭️ Skipped 0

Links

  • 🔗 Device Farm Run: View on AWS Device Farm
  • 🔗 Workflow: View Details
  • 📋 Run ARN: arn:aws:devicefarm:us-west-2:833707431398:run:cef7531e-44ed-4ddf-a349-a4b0f72f680d/6dd6e40a-60f4-4452-a676-25c51b3b8e88

Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

🧪 C++ Test Coverage Report

Coverage:

📊 Detailed Coverage
Filename                         Regions    Missed Regions     Cover   Functions  Missed Functions  Executed       Lines      Missed Lines     Cover    Branches   Missed Branches     Cover
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
NmtLazyInitializeBackend.cpp          47                 0   100.00%           7                 0   100.00%          67                 0   100.00%          24                 2    91.67%
NmtLazyInitializeBackend.hpp           2                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
TranslationModel.cpp                 162                49    69.75%          23                 3    86.96%         326                65    80.06%          66                32    51.52%
TranslationModel.hpp                   1                 0   100.00%           1                 0   100.00%           1                 0   100.00%           0                 0         -
nmt.cpp                               72                22    69.44%           9                 1    88.89%         135                28    79.26%          38                12    68.42%
nmt.hpp                               51                 4    92.16%          11                 2    81.82%          53                 4    92.45%          28                 0   100.00%
nmt_beam_search.cpp                  116                25    78.45%          10                 3    70.00%         254                32    87.40%          74                17    77.03%
nmt_graph_decoder.cpp                164                78    52.44%          15                 7    53.33%         541               161    70.24%         112                69    38.39%
nmt_graph_encoder.cpp                 54                13    75.93%           3                 0   100.00%         268                33    87.69%          36                15    58.33%
nmt_loader.cpp                       283                80    71.73%          14                 0   100.00%         786               109    86.13%         148                71    52.03%
nmt_state_backend.cpp                199                53    73.37%          20                 0   100.00%         431                86    80.05%         122                53    56.56%
nmt_tokenization.cpp                  88                21    76.14%           8                 0   100.00%         135                36    73.33%          58                25    56.90%
nmt_utils.cpp                         24                 4    83.33%           3                 0   100.00%          36                 5    86.11%          16                 7    56.25%
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
TOTAL                               1263               349    72.37%         125                16    87.20%        3034               559    81.58%         722               303    58.03%

@github-actions

Copy link
Copy Markdown
Contributor

✅ E2E Mobile Test Results - iOS

Overall Status: PASSED
Device Farm Result: PASSED
Platform: iOS
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 404485f

Test Summary

Metric Count
Total Tests 3
✅ Passed 3
❌ Failed 0
⏭️ Skipped 0

Links

  • 🔗 Device Farm Run: View on AWS Device Farm
  • 🔗 Workflow: View Details
  • 📋 Run ARN: arn:aws:devicefarm:us-west-2:833707431398:run:cef7531e-44ed-4ddf-a349-a4b0f72f680d/dd3c19e9-e876-4141-8199-56dd1736e2ab

Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

✅ E2E Mobile Test Results - Android

Overall Status: PASSED
Device Farm Result: PASSED
Platform: Android
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 404485f

Test Summary

Metric Count
Total Tests 6
✅ Passed 6
❌ Failed 0
⏭️ Skipped 0

Links

  • 🔗 Device Farm Run: View on AWS Device Farm
  • 🔗 Workflow: View Details
  • 📋 Run ARN: arn:aws:devicefarm:us-west-2:833707431398:run:cef7531e-44ed-4ddf-a349-a4b0f72f680d/ccd1ff02-9c47-45b4-9bb9-1cdaa111400e

Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@iancris

iancris commented Apr 22, 2026

Copy link
Copy Markdown
Contributor Author

/review

@olyasir olyasir mentioned this pull request Apr 22, 2026
4 tasks
@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - iOS

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: iOS
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 25f025c

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - Android

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: Android
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 25f025c

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - iOS

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: iOS
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 25f025c

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - Android

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: Android
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 25f025c

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - iOS

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: iOS
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 25f025c

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - Android

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: Android
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 25f025c

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - iOS

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: iOS
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 1f9897f

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

@github-actions

Copy link
Copy Markdown
Contributor

❌ E2E Mobile Test Results - Android

Overall Status: FAILED
Device Farm Result: UNKNOWN
Platform: Android
Addon: @qvac/translation-nmtcpp
PR: #1617
Commit: 1f9897f

Test Summary

Metric Count
Total Tests 0
✅ Passed 0
❌ Failed 0
⏭️ Skipped 0

Links


Automated E2E mobile testing powered by AWS Device Farm
Tests located in: test/mobile/

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants