Up & Running Swift for TensorFlow with Jupyter on macOS

Hello everyone,

As you all know Swift for TensorFlow (S4TF) is at its early stages and note fully developed. However, I would love to start using it locally on my mac and get more familiar with syntax and etc. For the last couple of days I struggled to install S4TF alongside jupyter. It took me a while to figure out some hackery to do it. I would like to share it with anyone who has the same issue.

First note that there two repositories on GitHub for S4TF, one maintained by apple as dev branch of Swift:
https://github.com/apple/swift/tree/tensorflow
And the other maintained by TF team:
https://github.com/tensorflow/swift

Installation page on the later provides links to binary releases for S4TF. Using any of the installers marked Xcode, will successfully install S4TF on your mac. However, not all of them are a suitable candidate for jupyter. As of the time of writing this forum the stable release is incompatible with jupyter. For it to be compatible the lldb python package in S4TF toolchain must be configured with python3. This is something that they have considered in the later releases. There is an easy way to check, install one of the release listed in installation and then in terminal execute:

lldb -P

the result will look something like:

/Library/Developer/Toolchains/swift-tensorflow-DEVELOPMENT-2019-08-28-a.xctoolchain/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python

This is the path for lldb python library. Navigate to the library directory by executing:

cd  `lldb -P`/lldb

Now you should make sure that the file _lldb.so is linked to built for python 3.x. Simply

otool -L _lldb.so | grep Python

The output will tell you if lldb is configured for python version 3.x. If that is not the case, you first must uninstall the toolchain by launching Xcode. Click on “Xcode” in menu bar, then select “Preferences…”. Click on “Components”. Right click on the swift toolchain and then hit “move to trash”. Look for another version on installation page and repeat this process until you find one that is configured for python 3.x.

When you find a version that supports python 3.x most likely it is linked to a non-existent file. In my case “_lldb.so” was linked to

/usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/Python (compatibility version 3.7.0, current version 3.7.0)

But fear not! This can be resolved. Find the equivalent file in your python 3 installation and then use install_name_tool command to right this wrong:

sudo install_name_tool -change <wrong_path> <right_path> _lldb.so

For example:

sudo install_name_tool -change /usr/local/opt/python/Frameworks/Python.framework/Versions/3.7/Python /Library/Frameworks/Python.framework/Versions/3.7/Python _lldb.so

Finally let’s make sure that lldb can be loaded in to python 3.

export PYTHONPATH=$(lldb -P):$PYTHONPATH
python3 -c "import lldb"

If this runs without any errors you are good and ready to install S4TF jupyter kernel (assuming that jupyter is already installed on your mac).

In a directory of your choice

git clone https://github.com/google/swift-jupyter.git
cd swift-jupyter
python3 -m venv venv
. venv/bin/activate
pip install -r requirements.txt
python register.py --sys-prefix --swift-toolchain /Library/Developer/Toolchains/swift-latest

Finally run Jupyter

. venv/bin/activate
jupyter notebook

But wait it is not over! Create a new swift notebook and try to execute a line of swift to see if the installation was successful. In my case it was not. Checking the terminal I saw that the error “Exception: Could not start debugger” coming from file swift_kernel.py. After doing some digging I realized that this is probably a bug so I edited the file swift_kernel.py and commented out the following two lines:

    #if not self.debugger:
    #    raise Exception('Could not start debugger')

run jupyter again:

jupyter notebook

And voila we have S4TF running in jupyter on mac.

9 Likes

Did you discover if there is a Docker container that will expose Jupyterlab with Swift?

3 Likes

Thanks for the info. It did help me setting it up but I used ./lldb -P since there’s another lldb under /usr/bin/

Also, instead of searching in vain for a macOS build that is compatible with Swift Jupyter, you can build it from source which I managed to do after running into and resolving many build issues.

Please let me know if you need help compiling it from source or you need a binary build for macOS.

Best regards,
–Nghi Tran (Nathan)

But it’s only available for Linux not macOS. They say you’ll have to build your own toolchain. But my MacBook Pro is slow for that!

Sorry for the late reply. Yes, indeed making a toolchain is extremely intensive. I have a descent MacBook and it takes about four hours. Since the versions are buggy and they change very often I completely bailed on the idea. Now I use the docker image it takes about 15 minutes to download and setup.

1 Like

Can you post docker commands and docker image you use?

1 Like

Hi Wojtekcz,

This is the recipe I use:

Building:

  1. Clone the repository by executing:
    git clone https://github.com/google/swift-jupyter.git
  2. Enter the folder and build the docker image:
    cd swift-jupyter
    docker build -f docker/Dockerfile -t swift-jupyter .

Running:

  1. From now on you can start using S4TF in jupyter by executing
    docker run -p 8888:8888 --cap-add SYS_PTRACE -v notebook_path:/notebooks swift-jupyter
    remember to replace notebook_path with relative or absolute path that you want to directory on your mac that you want to contain the notebooks
  2. you will see a link with a token in the terminal, something like:
    http://127.0.0.1:8888/?token=55a66c6cc0645620ce87216c9c9bb88472c35e6ad4cb4e48
    copy this to your browser and you are all set

Stopping:

  1. The jupyter server cannot be stopped like in normal situations i.e. by pressing control+c. You have to stop the docker image from running. This is the one-liner command I use to do so
    docker stop $(docker ps -q -f ancestor=swift-jupyter)

Best,
Sina

6 Likes

Thanks a lot.

swift-jupyter/docker/Dockerfile:
FROM gcr.io/swift-tensorflow/base-deps-cuda10.1-cudnn7-ubuntu18.04

I seem to recall that in the past GPU tensorflow package wouldn’t work on CPU only machine.

So you’ve built CUDA docker image and it works on a Mac? That would be awesome.

I have a MacBook with no GPU and it works!

Hello! I have tried to follow the instructions you’ve laid out for setting this up, but for some reason when I check my path in the jupyter notebook it is running python3.6. I can’t figure out how to get certain packages i need like networkx as a result. Do you have any ideas about what i’m doing wrong?

Hi Daniel,

I am not exactly sure what the problem is? Were you able to build the docker image? Did you manage to run the image?

Yeah. So I’ve got docker running and I can do most of what I need with things as they are. However, if I run “let nx = Python.Import(“networkx”)” I get an error about networkx not being found as a module. I am not sure why this is happening because I have networkx installed via pip.

Going backwards a bit, at the step in the original tutorial where you run something like:
sudo install_name_tool -change usr/local/opt/python/Frameworks/Python3.framework/Versions/3.7/Python3 /Library/Frameworks/Python.framework/Versions/3.8/Python

I get a segmentation fault when running the test commands you posted after that instruction…

I am not sure if that has anything to do with the first problem though…

Hi Daniel do not use the tutorial I wrote at the beginning. That does not work anymore because swift is changing so much. The easiest way is the docker now.

Yes you probably won’t see some packages that you installed on your Mac on the docker. Think of docker as a VM you have not installed networkx on that vm have you? So you need to rebuild the docker with extra commands. Add the following line to your docker file and rebuild;

RUN pip3 install networkx

Ahhhhh. That makes sense. Sorry for such a silly question; I had never used docker before. Thank you!

Just a stupid (probably) question. I wanted to use other Apple frameworks in Swift running under Jupyter. I’ve run the docker image, it works ok. But I cannot use any of the system frameworks, such as Metal.framework for example. When I do import Metal, it doesn’t complain, but when whatever symbols that should have been imported from it are unavailable.

When running inside Docker, you’re actually running within a Linux VM running on your mac hardware. Thus it’s expected that Apple system frameworks (e.g. Metal) are unavailable. Does that make sense?

Note: I think it’s probably a bug that import Metal doesn’t complain however…

Thanks! Makes sense. It’s a pity I can’t get jupyter-swift working on Mac, the original habitat of Swift :slight_smile:

Since python 2 will soon be discontinued Apple has to upgrade macs default python to 3. After that you won’t need using Docker anymore

My understanding is that this is not Apple’s problem. It’s just that _llbb.so that comes with the XCode11 distribution of S4TF is linked against Python2.7. This could be fixed by whoever makes the distribution of S4TF.

Additionally, maybe the distribution for MacOS doesn’t need to ship its own LLDB, since it’s already included with MacOS. Potentially, the toolchain can just link to the existing frameworks on MacOS. However, I know very little about this to judge.

It would be nice, if I am able to use S4TF in the future on MacOS directly, if I could also use the native MacOS frameworks like Metal and MetalPerformanceShaders. I am afraid that it may still not be possible, of the toolchain is shipped with some pre-baked set of tools.