Sandbox - nikolaradulov/SLAMFuse GitHub Wiki

NOTE: Created to test how good of a solution docker represents for the dependency issues of slambench.

Main Idea

The sandbox environment contains 3 main parts:

  • a loader program that gets passed a shared library, loads it and executes a function ''mock``. This is done to replicate the way SLAMBench behaves when ran against an algorithm.
  • A pseudo algorithm implementation ''app1.cpp``. This just implements a small function that draws a ascii figure of darth vader and outputs a message dependent on the version of the dynamic library it's meant to use. To be more clear it uses to fake libraries created to mock depedency issues seen in SMALBench. One is static one is dynamic. Both come as version 1.0 and 2.0 s.t the versions are mutually exclusive. As such if the version installed is not supported it app1.cpp will throw a compilation error for the static library and a runtime error for the dynamic one.
  • Another pseudo alforithm using only version 2.0 of the libraries mentioned above. Same logic applies

The aim is to 2 volumes, one for each app which contain all the needed dependecies. These can then be mounted in the loader container for an easy way to run the two apps without having to deal with the hassle of dependency conflicts.

Showing the conflict

The first point to be made is that often conflicting versions of libraries are required by algorithms in slambench. When this happens the current solution is to switch the library verson every time you wish to run the algorithm. This is annoying. The new solution we are working on involves using containers and docker volumes in order to provide each algorithm as a plugable entity: simply mount the appropriate volume and run the container.

Within the sandbox the dependency issue can be easily replicated:

  1. Go to the version1 folder
  2. install the static library: sh install_asciidraw.sh
  3. install the dynamic librarty sh install_shared.sh
  4. compile the program: g++ -shared -fPIC app1.cpp -o app1.so -lasciidraw
  5. go to Loader folder
  6. run the loader with the shared object created ./loader ../version1/app1.so The program should display darth vader once and the a message confirming that you are using the right version of the dynamic library
  7. Now if you switch to version2, and try to compile the other program using g++ -shared -fPIC app2.cpp -o app2.so -lasciidraw, it should throw a compilation error due to the wrong version of asciidraw being installed.
  8. This can be solved by updating the library. Within version2 run sh install_asciidraw.sh. If you recompile it should then be successful.
  9. The program can now be run. Witch to Loader and ./loader ../version2/app2.so. # Darth vaders wikll be displayed and then the program should throw a runtime error complaining that it could not find the function compute. This is becuase the shared library is using an outdated version.
  10. To solve this switch back to version2 and run sh install_shared.sh. The program should successfully run afterwards.
  11. To successfully run app1 now, the dynamic library should be downgraded back to version 1, ortherwise a runtime error will happen.

Containers save the day

So what if instead of having to go trough all this whenever one of the programs needs to be run, we would prepare everything once and then never have to worry about it again. This is where containers come into play. We create a container for the loader and then one volume for each application where we pack the compiled application itself and it's dependencies.

  1. Create a volume for app1: docker volume create version1-vol
  2. Create a volume for app2: docker volume create version2-vol
  3. We now need to make 2 containers, one for each app. These containers will create and build all the dependencies and compile the application, after which they will fill the volumes with the required data:
    • Build the container. In this phase the libraries are installed and the application is built: docker build . -t slambench/version1
    • Run the container. In this stage everything is copied to the mounted volume: docker run --mount source=version1-vol,target=/mnt/volume slambench/version1
  4. Do the same for app2
  5. Build the loader container. Inside Loader do : docker build . -t slambench/loader
  6. Now you simply have to run the container wioth the volume you wish mounted. Beware that to make it closer to current SLAMBench implementation the location of the shared libnery to be loaded must be passed as an argument to the docker run command: docker run --mount source=version1-vol,target=/usr/local slambench/loader /usr/local/app1.so. This could be modified such that the container always loads the same named file from the same location. The file would always be on the volume and as such only mounting to the right place would be required.