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

WebAssembly Support #920

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open

WebAssembly Support #920

wants to merge 6 commits into from

Conversation

thewtex
Copy link
Contributor

@thewtex thewtex commented Jun 21, 2023

  1. Fixes build issues with WebAssembly (Wasm) toolchains (both Emscripten and WASI)
  2. Remove file-IO for Wasm builds because Wasm requires special handling of filesystem access and the ITK libraries required for IO will bloat the WASM binary size.

@thewtex thewtex requested review from N-Dekker and ntatsisk June 21, 2023 15:52
@thewtex
Copy link
Contributor Author

thewtex commented Jun 21, 2023

Core/CMakeLists.txt Outdated Show resolved Hide resolved
@@ -270,6 +275,10 @@ template <class TElastix>
unsigned int
PolydataDummyPenalty<TElastix>::ReadMesh(const std::string & meshFileName, typename FixedMeshType::Pointer & mesh)
{
#ifdef __wasm32__
log::error(std::ostringstream{} << "File IO not supported in WebAssembly builds.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please pass the string directly to log::error, without std::ostringstream{} <<. (ostringstream is only necessary when a string needs to be built by << insertions). So please just:

log::error("File IO not supported in WebAssembly builds.");

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, maybe an itkExceptionMacro("File IO not supported in WebAssembly builds."); would be more appropriate, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we could do both -- WebAssembly has limited C++ exception support at the moment, so it will help to also log an error message.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, can you please explain what you mean by limited C++ exception support?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current Emscripten toolchain adds a JavaScript shim for C++ exceptions, and I added a shim for C++ exceptions in WASI that calls abort();. There is newer, experimental WASM-exceptions in some newer toolchains, but I have not enabled them by default.

Comment on lines +179 to +181
#ifndef __wasi__
std::lock_guard<std::mutex> mutexHolder(m_Mutex);
#endif
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does WASI support multi-threading? Specifically, will this ComputeImageExtremaFilter run using multiple threads in parallel?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the default WASI toolchain does not support multi-threading. This is being improved, but we need these for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, still not very happy about having #ifndef __wasi__ all over the place. Would it be an idea to have a "dummy" mutex class (that does not do anything) for single-threaded builds.

#ifdef ELX_SINGLE_THREADED_BUILD
  using ElastixMutexType = DummyMutex;  // Mutex-like dummy type that does nothing
#else
  using ElastixMutexType = std::mutex;
#endif 

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I do not see how a dummy mutex type addresses the std::lock_guard and the mutex class members.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::lock_guard should be able to support any "mutex-like" type, that has a lock() and an unlock() member function. So for example, would the following code compile on WASI? https://godbolt.org/z/oP5T6Pn35 Can you please try that out?

#define ELX_SINGLE_THREADED // For WebAssembly Support

#include <mutex>

// Mutex for single-threading, does nothing.
class SingleThreadedMutex
{
  public:
    void lock() {}
    void unlock() {}
};

// The MutexType type alias:
#ifdef ELX_SINGLE_THREADED
using MutexType = SingleThreadedMutex;
#else
using MutexType = std::mutex;
#endif

// Use case:
MutexType mutexVariable;
std::lock_guard<MutexType> lockGuard(mutexVariable);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thewtex Would it be helpful to you if I would implement such a SingleThreadedMutex for elastix, that would replace std::mutex when a CMake option like ELX_SINGLE_THREADED would be ON?

@thewtex thewtex force-pushed the wasm branch 3 times, most recently from 014ec6b to fe31f0c Compare June 21, 2023 19:07
Core/CMakeLists.txt Outdated Show resolved Hide resolved
Core/CMakeLists.txt Outdated Show resolved Hide resolved
N-Dekker added a commit that referenced this pull request Jun 22, 2023
Added support for `ELASTIX_BUILD_EXECUTABLE`, allowing to switch off building the elastix and transformix executables, while still building the libraries.

Basically reverts pull request #232 commit a0c161a "STYLE: Remove ELASTIX_BUILD_EXECUTABLE option -- always build lib + exe"

The ability to suppress building the executables appears necessary for WebAssembly support, as requested by Matt McCormick at #920
N-Dekker added a commit that referenced this pull request Jun 22, 2023
Added support for `ELASTIX_BUILD_EXECUTABLE`, allowing to switch off building the elastix and transformix executables, while still building the libraries.

Basically reverts pull request #232 commit a0c161a "STYLE: Remove ELASTIX_BUILD_EXECUTABLE option -- always build lib + exe"

The ability to suppress building the executables appears necessary for WebAssembly support, as requested by Matt McCormick at #920
N-Dekker added a commit that referenced this pull request Jun 23, 2023
Added support for `ELASTIX_BUILD_EXECUTABLE`, allowing to switch off building the elastix and transformix executables, while still building the libraries.

Basically reverts pull request #232 commit a0c161a "STYLE: Remove ELASTIX_BUILD_EXECUTABLE option -- always build lib + exe"

The ability to suppress building the executables appears necessary for WebAssembly support, as requested by Matt McCormick at #920
N-Dekker added a commit that referenced this pull request Jun 23, 2023
Added support for `ELASTIX_BUILD_EXECUTABLE`, allowing to switch off building the elastix and transformix executables, while still building the libraries.

Basically reverts pull request #232 commit a0c161a "STYLE: Remove ELASTIX_BUILD_EXECUTABLE option -- always build lib + exe" (August 25, 2020).

The ability to suppress building the executables appears necessary for WebAssembly support, as requested by Matt McCormick at pull request #920
N-Dekker added a commit that referenced this pull request Jun 23, 2023
Added support for `ELASTIX_BUILD_EXECUTABLE`, allowing to switch off building the elastix and transformix executables, while still building the libraries.

Basically reverts pull request #232 commit a0c161a "STYLE: Remove ELASTIX_BUILD_EXECUTABLE option -- always build lib + exe" (August 25, 2020).

The ability to suppress building the executables appears necessary for WebAssembly support, as requested by Matt McCormick at pull request #920
@@ -22,7 +22,6 @@
#include "elxConversion.h"
#include "elxDeref.h"

#include "itkImageFileCastWriter.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry to disagree about the subject line, "BUG: Remove unused itkImageFileCastWriter includes". Each of the three hxx files modified by this commit does use "itkImageFileCastWriter.h". Specifically, each of them has a call to itk::WriteCastedImage. It's certainly not a bug.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The way the include was added causes build errors when the include needs to avoided and causes build errors. This is a bug. BUG here does not refer to the use case referenced.

thewtex added a commit to InsightSoftwareConsortium/ITKElastix that referenced this pull request Jul 10, 2023
@thewtex
Copy link
Contributor Author

thewtex commented Aug 26, 2023

Rebasing on main

Currently unsupported.

Addresses:

```
/work/wasi-build/_deps/elx-src/Common/itkComputeImageExtremaFilter.h:132:8: error: no type named 'mutex' in namespace 'std'
  std::mutex m_Mutex{};
  ~~~~~^
```
Reduces Wasm binary size and addresses the build error:

```
wasm-ld-15: error: _deps/elx-build/bin/libelastix-5.1.a(elxComponentLoader.cxx.o): undefined symbol: __cxa_thread_atexit
wasm-ld-15: error: _deps/elx-build/bin/libelastix-5.1.a(elxComponentLoader.cxx.o): undefined symbol: __cxa_thread_atexit
wasm-ld-15: error: _deps/elx-build/bin/libelastix-5.1.a(elxComponentLoader.cxx.o): undefined symbol: __cxa_thread_atexit
wasm-ld-15: error: _deps/elx-build/bin/libelastix-5.1.a(elxComponentLoader.cxx.o): undefined symbol: __cxa_thread_atexit
wasm-ld-15: error: /ITK-build/lib/libitkgdcmCommon-5.4.a(gdcmSystem.cxx.o): undefined symbol: gethostname
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5PLint.c.o): undefined symbol: H5PL_CLOSE_LIB
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5system.c.o): undefined symbol: tzset
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5Fint.c.o): undefined symbol: realpath
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5FDcore.c.o): undefined symbol: itk_Pflock
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5FDcore.c.o): undefined symbol: itk_Pflock
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5PLint.c.o): undefined symbol: H5PL_GET_LIB_FUNC
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5PLint.c.o): undefined symbol: H5PL_GET_LIB_FUNC
wasm-ld-15: error: /ITK-build/lib/libitkhdf5-static-5.4.a(H5PLint.c.o): undefined symbol: H5PL_GET_LIB_FUNC
```
Avoid Wasm binary size issues and file access issues.
We still need to load the elastix components.
In itkElastixRegistrationMethod.hxx.
@thewtex
Copy link
Contributor Author

thewtex commented Oct 1, 2023

Rebase

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

Successfully merging this pull request may close these issues.

2 participants