See also: development guide.

Objective

This document helps you to get the development setup on Mac for working with Apache MXNet codebase. This document covers installing all required tools and packages, IDEs, debugging tools and is intended for developers who wants to dive into MXNet codebase, develop, debug, test and contribute. 

We will be using Visual Studio Code (VSCode) by Microsoft, as IDE because of the following reasons:

  1. It is free and powerful IDE with support for multiple programming languages - C++, Python, JS and more
  2. It provides easy to use frameworks for debugging. You can easily prepare debug configurations for mixed system debug - Example: You have front end code in Python and backend in C++. You can debug seamless end to end from Python to C++ and back.
  3. It has many useful extensions - CudaCPP for syntax highlighting of CUDA CPP code, markdown, docker, React and more.

Please note that - this is one of the option for your development setup, and is not default/recommended/best option! You can always have Vim, CLion, emacs and many other IDEs/code editors of your choice.

Step 1 - Install IDEs and required tools

1.1 Install XCode for Mac 

If not already installed, download and install Xcode (or install it from the App Store) for macOS. Xcode is an integrated development environment for macOS containing a suite of software development tools like C/C++ compilers, BLAS library and more.

Note: You can also just install XCode Command Line Tools for this setup.

xcode-select --install

1.2 Install brew

Refer here for the steps - https://brew.sh/

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

1.3 Install wget

brew install wget

1.4 (optional, recommended) Install git-secrets - This will help you prevent committing credentials and secrets

brew install git-secrets

1.5 Install VSCode for Mac

Follow the instructions from VSCode page - https://code.visualstudio.com/docs/setup/mac

To summarize - You will download the VSCode for mac, double click on downloaded archive, drag Visual Studio Code app to Applications folder. 

When you open VSCode for first time, right click on the icon in the below menu bar choose options and keep in dock. So that next time you can just click on VSCode from menu bar.

Install useful VSCode extensions

  • Open VSCode
  • Go to View → Extensions
  • In the search bar type - “C/C++”.
    • Install extension “C/C++ IntelliSense, debugging, and code browsing” by Microsoft.
      (Some developers have reported bugs using this extension on MacOS Yosemite. An alternative is to install the extension "CodeLLDB" by Vadim Chugunov)
  • In the search bar type - “CodeLLDB”.
    • Install extension CodeLLDB. (There are some issues on debugging with macos LLDB, see this )
  • In the search bar type - “Python”. 
    • Install extension “Python extension - Linting, Debugging (multi-threaded, remote), Intellisense, code formatting...” by Microsoft.
  • In the search bar type - “CudaCPP”.
    • Install extension “vscode-cudacpp - CUDA C++ language support for Visual Studio Code” by kriegalex.

1.6 Install Anaconda 

Option 1 - Use Anaconda graphical installer from https://www.anaconda.com/download/#macos and click on the package to follow through the installation instructions. 

OR,

Option 2 - Install via the script

wget https://repo.anaconda.com/archive/Anaconda3-5.2.0-MacOSX-x86_64.sh
bash Anaconda3-5.2.0-MacOSX-x86_64.sh

Note: You can also install Miniconda or VirtualEnv instead of full blown Anaconda. Anaconda is used here for convenience as it brings all required packages like - jupyter, numpy, h5py and more. At the same time, Anaconda is a bloated group of packages, so may use more memory, through many unused packages, than required for the development.

1.7 Setup Git Configurations

vi ~/.gitconfig

# Set the below values in the gitconfig file

# This is Git's per-user configuration file.
[user]
# Please adapt and uncomment the following lines:
        name = <Your Username>
        email = <Your email ID attached with Github account>

Step 2 - Get into MXNet codebase 

2.1 Fork the Apache MXNet (incubating) repository

2.2 Get MXNet source on your machine

mkdir workspace
cd workspace
git clone --recursive https://github.com/<Your Github username>/incubator-mxnet

2.3 Setup dependencies for MXNet

brew update
brew tap homebrew/core
brew install pkgconfig
brew install opencv
brew install graphviz
pip install graphviz
pip install opencv-python
pip install pytest

2.4 Build MXNet core engine(After MXNet 1.6 release)

cp config/darwin.cmake config.cmake
mkdir build; cd build
CC=clang-10 CXX=clang++-10 CXXFLAGS='-fstandalone-debug' cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_CUDA=0 ..; ninja

Or with optimization

CC=clang-10 CXX=clang++-10 CXXFLAGS='-fstandalone-debug' cmake -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_CUDA=0 ..; ninja

Note: the exact versions of `clang` and `clang++` may be different on your computer. For example, this is an example of a command that currently works on MacOS Catalina after installing xcode

CC=clang CXX=clang++ CXXFLAGS='-fstandalone-debug' cmake -GNinja -DCMAKE_BUILD_TYPE=Debug -DUSE_CUDA=0 ..; ninja

To clean any previous build, use:

rm -rf build

2.5 Build MXNet Python binding

cd python
pip install -e .

2.6 Run an example (terminal)

To verify our installation, we will train a simple  Multi Layer Perceptron (MLP) model for hand written digit recognition (MNIST) dataset.

cd ..
python example/image-classification/train_mnist.py

2.7 Run a test case (terminal)

Typically, you implement the core logic in CPP, write python binding and write a python based test case to verify. MXNet python tests uses 'pytest'.

Let us run one single unit test for 'dot operator'

pytest tests/python/unittest/test_operator.py::test_dot

OR, you can run all operator tests

pytest tests/python/unittest/test_operator.py

OR, all unit tests

pytest tests/python/unittest/

Step 3 - Open MXNet codebase in VSCode - Develop and Debug

  1. File → Open → Select the MXNet directory.
      • View → Debug
      • Click on the Current configuration drop-down (in screenshot below it says "No Configurations")Setup VSCode for Debugging Python and C++ code
    • In the drop-down choose "Add Configuration"
    • Choose "Python" as the configuration type
    • And then you'll see the new configuration file "launch.json" with few default debug configurations. Delete all the contents and copy below provided launch.json.



Copy below snippet to 'launch.json' and save. We have 3 launch configurations below:

  1. Launch a C++ code for debug with lldb
  2. Attach to a process to debug a C++ code with lldb
  3. Launch a python code for debugging

Note: I have used '/anaconda3/bin/python' as a launch process for all python programs. If your python is in different location, set this accordingly. You can use 'which python' command on terminal to find the location of default python program in your machine.

{
    // Use IntelliSense to learn about possible attributes.
    // Hover to view descriptions of existing attributes.
    // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "lldb Attach Debug",
            "type": "lldb",
            "request": "attach",
            "program": "/anaconda3/bin/python",
            "processId": "${command:pickProcess}"
        },
        {
            "name": "lldb Launch Debug",
            "type": "cppdbg",
            "request": "launch",
            "program": "${file}",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "lldb"
        },
        {
            "name": "python Launch Debug",
            "type": "python",
            "request": "launch",
            "stopOnEntry": false,
            "pythonPath": "/anaconda3/bin/python",
            "program": "${file}",
            "cwd": "",
            "console": "none",
            "env": {},
            "envFile": "${workspaceRoot}/.env"
        },

    ]
}

2.8 Debug a test case

Let us debug a unit test to see how we can debug a Mix of Python and C++ codebase.


  1. Open 'incubator-mxnet/tests/python/unittest/test_operator.py
  2. Go to test case - 'test_new_softmax()'. We will debug softmax operator. (Note: You can copy the softmax test function to the top of file to avoid waiting for other tests to pass)
  3. Add breakpoint. You can click to left of the line number where you want to add a breakpoint for debugging.


  1. Go to softmax implementation code - 'incubator-mxnet/src/operator/nn/softmax-inl.h'
  2. Add breakpoint in the softmax function - 'inline void Softmax(..)'


Now, let us debug.

Step 1: Start Python code in debug mode

  1. Go back to the test_operator.py file. 
  2. Open Debug window: View→ Debug
  3. From the debug dropdown, select 'Python Launch Debug'. This was the debug configuration we had created in earlier steps. This will launch the current python file (test_operator.py) in debug mode.


At the top you can see the debugging controls. (Or, you can use shortcut commands, see appendix below)


 


Now, you should hit the debug point in your softmax test function like below.


Step 2: Start lldb debugger and attach to the python program being tested


From Debug dropdown, select 'lldb Attach Debug'. Select and start. Now, choose the 'test_operator.py' python process to attach.



You can now see that debug point is attached to the softmax CPP implementation code.


 

On the left, debug panel, you use 'python' and 'lldb' debugger to switch between 


 


Now, you can continue execution, debug, inspect values and more.



You can also use Debug console to inspect and debug.


NOTE: If your C++ code debug point is not active, probably it means, symbols loaded in IDE is not the same that your python code is using. Most likely this will happen if you have pip installed mxnet and not compiled and build from mxnet source in the workspace. My pip list of search for MXNet looks like below, observe that MXNet python package is coming from my workspace.

$ pip list | grep mxnet
mxnet                              1.3.0     /Users/<user_id>/Documents/workspace/mxnet/incubator-mxnet/python

Creating your first Pull Request


Follow instructions from this Git Setup and Workflow

At high level below are the steps you do to contribute your changes: 

  • Set upstream for your repo in workspace to remote MXNet repo
  • Checkout a working branch that tracks the remote upstream
  • Make changes
  • Running all tests
  • Commit
  • Pull rebase
  • Push to working branch
  • Create Pull Request

Note: It would be good combine this document with Development Guide.

Next Steps (TODOs)

  1. Update steps for users with GPU on Mac.
  2. Remote Machine Setup - Local Mac and Remote cloud GPU instance with Ubuntu

References

  1. Brew - https://brew.sh/
  2. awslabs/git-secrets - https://github.com/awslabs/git-secrets
  3. Anaconda for Mac - https://conda.io/docs/user-guide/install/macos.html
  4. VSCode for Mac - https://code.visualstudio.com/docs/setup/mac
  5. VSCode CPP - https://code.visualstudio.com/docs/languages/cpp
  6. VSCode CPP Debugger - https://github.com/Microsoft/vscode-cpptools/blob/master/launch.md
  7. VSCode debugger options for Python - https://code.visualstudio.com/docs/python/debugging
  8. You can format an entire file with Format Document (⇧⌥F) or just the current selection with Format Selection (⌘K ⌘F) in right-click context menu.
  9. F10 → Step Over, F11 → Step Into, Shift+F11→ Step Out, F5 → Continue

Appendix

Helpful VSCODE shortcuts

  1. You can format an entire file with Format Document (⇧⌥F) or just the current selection with Format Selection (⌘K ⌘F) in right-click context menu.
  2. F10 → Step Over, F11 → Step Into, Shift+F11→ Step Out, F5 → Continue



  • No labels

1 Comment

  1. Great document.  Do you mind adding MKL-DNN steps in the plan of the next step?

    You can refer here: https://github.com/apache/incubator-mxnet/blob/master/MKLDNN_README.md#2