Clojure Neanderthal MKL acceleration out of the box

You can adopt a pet function! Support my work on my Patreon page, and access my dedicated discussion server. Can't afford to donate? Ask for a free invite.

August 6, 2020

Please share: .

New books are available for subscription.

Good news on a slow August day: you no longer have to install any system wide native library to use Neanderthal() on the CPU! It is enough to add an optional dependency to Bytedeco's MKL redistribution jar in you project configuration (Lein, deps, boot), and everything will work out of the box for you!

Did I have to do a lot of work to support it? Yes and no! No, in a sense that I only had to add 4 lines of Clojure code at the appropriate place in the depths of Neanderthal. No, in a sense that this is something that already worked if you added similar 4 lines of Clojure code in the appropriate place in you project. Yes, in a sense that Neanderthal was designed from the start to be technology-agnostic and support as many CPU, GPU, and other engines as Clojure programmers are eager to explore.

This is one small step code-wise, but a big leap convenience-wise. The major perceived pain point for the new users was the requirement to install MKL on your system. It is a simple step anyway. On Arch Linux it is literally pacman -Syu intel-mkl. That was all. But still, habits are strange beasts, and Clojure and Java programmers fight tooth and nail against using anything outside repository jars. Which is reasonable. But still… The performance benefits of MKL, CUDA, and OpenCL are enormous. Didn't matter for most people. Turn on the light! OK. There is light now :)

Of course, I still recommend using the system-wide MKL. That's 750 MB that can sit in your system instead of your jars. That's 750 MB that you don't have to update all the time if you don't like. 750 MB that can be used by other software on your machine (NumPy, TensorFlow, whatever).

However, I do appreciate that, if you're eager to try Neanderthal you would like to open your REPL and learn how to write high performance Clojure code right away, instead of fiddling with the configuration of your OS (especially if you're a Windows user). That's why this tiny update is major news.

So, let's show some code. The Hello World example in the Neanderthal repository has been updated with the optional MKL jar, and it looks like this:

(defproject hello-world "0.35.0"
  :dependencies [[org.clojure/clojure "1.10.1"]
                 [uncomplicate/neanderthal "0.35.0"]
                 ;;Optional. If bytedeco is not present, a system-wide MKL is used.
                 [org.bytedeco/mkl-platform-redist "2020.1-1.5.3"]]
  ;; If on Java 9+, you have to uncomment the following JVM option.
  :jvm-opts ^:replace [#_"--add-opens=java.base/jdk.internal.ref=ALL-UNNAMED"])

If the mkl-platform-redist jar is present, Neanderthal will load the native binaries for your OS from there. If it's not, it is expected that you have MKL somewhere on your system's LD_LIBRARY_PATH.

There's noting else that changed. Here's the old example from Hello World:

(ns hello-world.native
  (:require [uncomplicate.neanderthal
             [core :refer :all]
             [native :refer :all]]))

;; We create two matrices...
(def a (dge 2 3 [1 2 3 4 5 6]))
(def b (dge 3 2 [1 3 5 7 9 11]))
;; ... and multiply them
(mm a b)

Thanks to Tom (AKA joinr) for exploring this and (very politely and subtly) nudging me to automate it for all users.

Enjoy!

PS. And check out the books :)

Clojure Neanderthal MKL acceleration out of the box - August 6, 2020 - Dragan Djuric