TASMANIAN icon indicating copy to clipboard operation
TASMANIAN copied to clipboard

Build Tasmanian for apple m1

Open puat133 opened this issue 3 years ago • 12 comments

Hi,

First and foremost, I'd want to express my gratitude to the developer for their excellent job. I've utilized the Tasmanian library for several of my research projects. I recently acquired a machine with an Apple m1 processor. Installing Tasmanian straight from pip results in a broken library. I attempted to build the package using the build instructions. While the package was successfully built, I had the following issue while attempting to import Tasmanian:

OSError                                   Traceback (most recent call last)
<ipython-input-2-405aa3b9f3e0> in <module>
----> 1 import Tasmanian

/usr/local/share/Tasmanian/python/Tasmanian.py in <module>
     43 import TasmanianDREAM as DREAM
     44
---> 45 from TasmanianAddons import *
     46
     47 def useVerboseErrors(bVerbose):

/usr/local/share/Tasmanian/python/TasmanianAddons.py in <module>
     37 TasmanianInputError = TasmanianConfig.TasmanianInputError
     38
---> 39 pLibCTSG = cdll.LoadLibrary(TasmanianConfig.__path_libcaddons__)
     40
     41 type_1Dfunc = CFUNCTYPE(c_double, c_double)

/opt/homebrew/Caskroom/miniforge/base/envs/automatic_projection_filter/lib/python3.9/ctypes/__init__.py in LoadLibrary(self, name)
    458
    459     def LoadLibrary(self, name):
--> 460         return self._dlltype(name)
    461
    462     __class_getitem__ = classmethod(_types.GenericAlias)

/opt/homebrew/Caskroom/miniforge/base/envs/automatic_projection_filter/lib/python3.9/ctypes/__init__.py in __init__(self, name, mode, handle, use_errno, use_last_error, winmode)
    380
    381         if handle is None:
--> 382             self._handle = _dlopen(self._name, mode)
    383         else:
    384             self._handle = handle

OSError: dlopen(/usr/local/lib/libtasmaniancaddons.dylib, 0x0006): weak-def symbol not found '__ZN7TasGrid20TasmanianDenseSolver18solvesLeastSquaresINSt3__17complexIdEEEEvPKNS_19AccelerationContextEiiPT_iS9_'

How to solve this problem? Thanks

puat133 avatar Nov 25 '21 11:11 puat133

Hey, I'm glad you find Tasmanian useful.

The build is missing some symbol. I recommend against installing in /usr/local since it's hard to uninstall, but it should still work.

  • Are you using the latest master or the latest release?
  • What happens if you run:
/usr/local/bin/tasgrid -v
  • When you build it with CMake, did you use BLAS or ENABL_RECOMMENDED? You can try to skip ENABLE_RECOMMENDED and try to manually enable or disable BLAS.
  • Do you know if M1 used clang or gcc?

mkstoyanov avatar Nov 25 '21 12:11 mkstoyanov

Hi,

Thank you for your response. I am not an expert in compiling C/C++ programs from source code. As requested, here is some additional information:

  • I am using the master branch from Github.
  • Here is the output from `/usr/local/bin/tasgrid -v':
Tasmanian Sparse Grids  version: 7.8 (development)
                git commit hash: 1a7e80ebb387a225cc8c6d311f9a26589a4fc942
                cmake cxx flags: Debug,
                        license: BSD 3-Clause with UT-Battelle disclaimer
          OpenMP multithreading: Disabled
          GPU backend framework: none
         Available acceleration:  none
  • I use the following cmake configuration cmake -D Tasmanian_ENABLE_RECOMMENDED:BOOL=ON ..
-- Checking for LAPACK LQ factorization: not found (using QR instead)
--
-- Tasmanian 7.8 (development): summary of build options
--  -D CMAKE_BUILD_TYPE:STRING=Debug
--  -D CMAKE_INSTALL_PREFIX:PATH=/usr/local
--  -D CMAKE_CXX_FLAGS:STRING=
--  -D BUILD_SHARED_LIBS=ON
--  -D Tasmanian_ENABLE_OPENMP:BOOL=TRUE
--  -D Tasmanian_ENABLE_BLAS:BOOL=ON
--  -D Tasmanian_ENABLE_MPI:BOOL=OFF
--  -D Tasmanian_ENABLE_PYTHON:BOOL=ON
--  -D Tasmanian_ENABLE_CUDA:BOOL=OFF
--  -D Tasmanian_ENABLE_MAGMA:BOOL=OFF
--  -D Tasmanian_ENABLE_HIP:BOOL=OFF
--  -D Tasmanian_ENABLE_DPCPP:BOOL=OFF
--  -D Tasmanian_ENABLE_SWIG:BOOL=OFF
--  -D Tasmanian_ENABLE_FORTRAN:BOOL=OFF
--  -D Tasmanian_ENABLE_DOXYGEN:BOOL=OFF
--
-- Configuring done
-- Generating done
-- Build files have been written to: /Users/foo/GitHub/TAS
  • I'm not sure if clang or gcc is utilized for compilation. How can this be verified?
❯ clang++ --version
Apple clang version 13.0.0 (clang-1300.0.29.3)
Target: arm64-apple-darwin21.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
❯ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/c++/4.2.1
Apple clang version 13.0.0 (clang-1300.0.29.3)
Target: arm64-apple-darwin21.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

Thanks.

puat133 avatar Nov 26 '21 09:11 puat133

That's very strange, CMake says that BLAS has been enabled, but tasgrid doesn't show cpu_blas as an available acceleration mode.

Delete everything in your build folder and try using the following CMake command:

cmake -DCMAKE_BUILD_TYPE=Release -DTasmanian_ENABLE_PYTHON=ON ..

That will explicitly disable BLAS and hopefully things will work fine.

I have seen other BLAS issues on Apple even on the Intel chips. I may have to look into this.

mkstoyanov avatar Nov 26 '21 19:11 mkstoyanov

I tried your advice. Regrettably, it does not resolve the issue. 'make test' failed again on the python part:

The following tests FAILED:
	 14 - PythonIO (Failed)
	 15 - PythonAcceleration (Failed)
	 16 - PythonExceptions (Failed)
	 17 - PythonMakeUpdate (Failed)
	 18 - PythonRefine (Failed)
	 19 - PythonLearning (Failed)
	 20 - PythonMisc (Failed)
	 21 - PythonAddons (Failed)
	 22 - PythonDream (Failed)

Checking the log file, the same issue still persists:

22/22 Testing: PythonDream
22/22 Test: PythonDream
Command: "/opt/homebrew/Caskroom/miniforge/base/bin/python" "/Users/foo/GitHub/TASMANIAN/Build/Python/testTSG.py" "TestTasmanian.testDream"
Directory: /Users/foo/GitHub/TASMANIAN/Build/Python
"PythonDream" start time: Nov 27 19:26 +03
Output:
----------------------------------------------------------
Traceback (most recent call last):
  File "/Users/foo/GitHub/TASMANIAN/Build/Python/testTSG.py", line 17, in <module>
    import testExceptions
  File "/Users/foo/GitHub/TASMANIAN/Build/Python/testExceptions.py", line 2, in <module>
    import Tasmanian
  File "/Users/foo/GitHub/TASMANIAN/Build/Python/Tasmanian.py", line 45, in <module>
    from TasmanianAddons import *
  File "/Users/foo/GitHub/TASMANIAN/Build/Python/TasmanianAddons.py", line 39, in <module>
    pLibCTSG = cdll.LoadLibrary(TasmanianConfig.__path_libcaddons__)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/ctypes/__init__.py", line 460, in LoadLibrary
    return self._dlltype(name)
  File "/opt/homebrew/Caskroom/miniforge/base/lib/python3.9/ctypes/__init__.py", line 382, in __init__
    self._handle = _dlopen(self._name, mode)
OSError: dlopen(/Users/foo/GitHub/TASMANIAN/Build/Python/../Addons/libtasmaniancaddons.dylib, 0x0006): weak-def symbol not found '__ZN7TasGrid20TasmanianDenseSolver18solvesLeastSquaresINSt3__17complexIdEEEEvPKNS_19AccelerationContextEiiPT_iS9_'
<end of output>
Test time =   0.19 sec
----------------------------------------------------------
Test Failed.
"PythonDream" end time: Nov 27 19:26 +03
"PythonDream" time elapsed: 00:00:00
----------------------------------------------------------

Thank you.

puat133 avatar Nov 27 '21 16:11 puat133

The short version of the error is that one Tasmanian library could not find something that it needs from another Tasmanian library and/or symbol.

Not sure if this is due to some issue with OSX 11, M1, CMake, or all three.

I'll try to explore this further, but in the mean time you can try to manually set the paths to search for the libraries:

export TasmanianLibs=/Users/foo/GitHub/TASMANIAN/Build/Python/../Addons/:/Users/foo/GitHub/TASMANIAN/Build/Python/../DREAM/:/Users/foo/GitHub/TASMANIAN/Build/Python/../SparseGrids/
export LIBRARY_PATH=$LIBRARY_PATH:$TasmanianLibs
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$TasmanianLibs
export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:$TasmanianLibs
make test

You can also try to ignore "make test" and go straight for:

make install
make test_install

If the test-install works fine, then Tasmanian should be fine to use.

mkstoyanov avatar Nov 30 '21 22:11 mkstoyanov

Hi,

Thank you for your advice. That, too, did not work. I spend some investigation to determine how to list weak symbols from a dylib file. This is what I get:

❯ nm -a libtasmaniancaddons.7.8.0.dylib | grep __ZN7TasGrid20TasmanianDenseSolver18solvesLeastSquaresINSt3__17complexIdEEEEvPKNS_19AccelerationContextEiiPT_iS9_
                 U __ZN7TasGrid20TasmanianDenseSolver18solvesLeastSquaresINSt3__17complexIdEEEEvPKNS_19AccelerationContextEiiPT_iS9_

which means that the symbol is undefined in the libtasmaniancaddons.7.8.0.dylib file. I'm guessing that has something to do with compiler settings?

puat133 avatar Dec 01 '21 16:12 puat133

The TasmanianDenseSolver::solvesLeastSquares method is a template that is declared in tsgLinearSolvers.hpp then implemented and explicitly instantiated in tsgLinearSolvers.cpp which is then compiled inside libtasmaniansparsegrid.dylib. Either the library isn't found or the symbol is missing from the sparse grid library for some unknown reason, it may even be that the compiler is picking a wrong version of Tasmanian installed somewhere else in your system. It's really hard to debug this without an M1 for me to use.

Can you please try this with 7.7 which is the latest stable release as opposed to 7.8 which is the development version.

mkstoyanov avatar Dec 01 '21 18:12 mkstoyanov

Hi, I tested the method using version 7.7. Unfortunately, the same issue still appears. Hopefully, you'll be able to test TASMANIAN for the M1 machine in the future. Thank you.

puat133 avatar Dec 08 '21 14:12 puat133

I'll do what I can, but I cannot promise a timeline.

mkstoyanov avatar Dec 08 '21 15:12 mkstoyanov

Keep it open so we don't forget about this.

mkstoyanov avatar Dec 08 '21 15:12 mkstoyanov

For what it's worth, I'm encountering the same issue (down to the weak-def symbol) on an Intel-based Mac running Monterey. The issue persists after manually installing a GNU compiler other than AppleClang. I did not have this issue on Catalina with an Intel chip.

zbmorrow avatar Apr 07 '22 17:04 zbmorrow

That should make it easier to debug, Intel Macs are easier to find.

We have OSX 11 in the CI, but not OSX 12. I'll look into it.

mkstoyanov avatar Apr 07 '22 19:04 mkstoyanov

Finally found the problem:

  1. The issue was always specific to Python, C++ and the other interfaces were never affected.

  2. Unlike Windows, Linux and Intel OSX systems, Python on apple will not make symbols from loaded libraries available globally. The solution is to explicitly load the libraries with the command:

pLibTSG = ctypes.CDLL(__path_libsparsegrid__, mode = ctypes.RTLD_GLOBAL)
  1. As if the problem isn't enough, there is a second issue with the way arguments are defined for the C bindings. If there is a mismatch between the declared list of arguments and the ones actually used in the call, Python will not issue a proper warning or error message (only any operating system). Instead, Linux/Windows and Intel OSX will ignore the declared arguments and make the call with the provides list. If the list matches whatever the function expects, everything will work fine. However, in the case of a mismatch, the Apple silicon will simply segfault ...

It will be a few days before I update main repo and a few more before I update the pip-installer, but now that I have access to apple silicon, things will work.

Thanks to all that reported the issue and I'm sorry it took this long.

mkstoyanov avatar Mar 30 '24 21:03 mkstoyanov