Julia on Google Colab: Free GPU-Accelerated Shareable Notebooks

(Disclosure: While I work for Google, this is not an official Google product or announcement.)

tl;dr: For Julia on Colab with GPUs, first open this notebook and run the cell (takes ~15-20 minutes), then open this one to start using Julia.

Screenshot%20from%202018-09-21%2015-57-02

Recently, @denizyuret brought up on Slack that it would be nice if Google Colab supported Julia, especially for GPUs. I can’t promise anything about official or built-in support, but it turns out it’s possible to get this working entirely from the outside.

First, install CUDA 9.0 (the most recent version supported by the NVIDIA driver in the Colab GPU container) and Julia 1.0 using IPython line magic. This can be done by running the contents of this Colab notebook or by executing this code in a cell of a new notebook with the GPU runtime (either way, it takes 15-20 minutes):

!wget https://developer.nvidia.com/compute/cuda/9.0/Prod/local_installers/cuda-repo-ubuntu1604-9-0-local_9.0.176-1_amd64-deb
!dpkg -i cuda-repo-ubuntu1604-9-0-local_9.0.176-1_amd64-deb
!apt-key add /var/cuda-repo-9-0-local/7fa2af80.pub
!apt update -q
!apt install cuda gcc-6 g++-6 -y -q
!ln -s /usr/bin/gcc-6 /usr/local/cuda/bin/gcc
!ln -s /usr/bin/g++-6 /usr/local/cuda/bin/g++

!curl -sSL "https://julialang-s3.julialang.org/bin/linux/x64/1.0/julia-1.0.0-linux-x86_64.tar.gz" -o julia.tar.gz
!tar -xzf julia.tar.gz -C /usr --strip-components 1
!rm -rf julia.tar.gz*
!julia -e 'using Pkg; pkg"add IJulia; add CuArrays; add Flux; precompile"'

Feel free to add additional packages; you’ll also still be able to install them normally later.

Then open a new notebook in the same container (i.e., the same session) that declares julia-1.0 as its kernel. Unfortunately you can’t do this purely using the web UI; you must either use File -> Upload notebook and provide the following JSON as a .ipynb:

{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Julia on Colab.ipynb",
      "version": "0.3.2",
      "provenance": []
    },
    "kernelspec": {
      "name": "julia-1.0",
      "display_name": "Julia 1.0"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "metadata": {
        "id": "oMSuTc3pDlHv",
        "colab_type": "code",
        "colab": {}
      },
      "cell_type": "code",
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}

or you can simply open this notebook. If a saved notebook stops working with Julia (i.e., starts trying to run things in Python) you’ll have to run the installation notebook again.

Credits go to the intrepid folks who managed to get something similar working with node.js and R in this thread.

39 Likes

This is excellent news, thanks James! Does this install CUDA and Julia in your personal workspace? If you shared a Julia colab notebook, would the recipient need to go through the same process?

wow, it works quite well with Julia.
drop here my playground notebook.
thanks James!

I ported the Julia/Knet deep learning tutorial using @jekbradbury’s hack, so anyone can run them on a gpu using colab if they first initialize with the installation notebook. Here is the Google Drive link. You can also run directly from github adding the right prefix as @ekinakyurek mentioned on slack, for example: https://colab.research.google.com/github/denizyuret/Knet.jl/blob/6b114cb771c8ec779612730feafc8c5fba552664/tutorial/03.lin.ipynb

6 Likes

Is it possible to run Julia with TPU acceleration on Google Colab?

I tried running the first notebook and I managed to install Julia correctly and I can run it using “julia”. But, I can not start a new notebook with Julia preinstalled on it.

Can you tell me if this option still works or not?

see:

I finally managed to run it !
You will need to hyper-link the new notebook “julia-based” in the installation notebook to be able to open the notebook in the same container/session.

How did you hyperlink this?

You add a new text cell in the installation notebook and add a hyper link (you will find this option in the editor) for the julia-based notebook

Now the command apt install cuda install cuda 10, which produces the following error when loading CuArrays:

using CuArrays
┌ Info: Precompiling CuArrays [3a865a2d-5b23-5a0f-bc46-62713ec82fae]
└ @ Base loading.jl:1186
ERROR: LoadError: LoadError: UndefVarError: CUBLAS not defined

It is sufficient to run the commands in a Julia notebook to downgrade the CUDA version:

;apt-get install cuda-9-0
]build CuArrays

Alternatively, in the installation notebook one can directly specify version 9.0 by replacing

!apt install cuda gcc-6 g++-6 -y -q

with

!apt install cuda-9-0 gcc-6 g++-6 -y -q

In any case, thanks a lot to @jekbradbury for sharing this info about the julia notebook!

3 Likes

I just tried this. However, I have another error while using CuArrays

BoundsError(a=Array{Core.Compiler.BasicBlock, (32,)}[
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=1, last=7), preds=Array{Int64, (1,)}[32], succs=Array{Int64, (1,)}[2]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=8, last=14), preds=Array{Int64, (1,)}[1], succs=Array{Int64, (2,)}[5, 3]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=15, last=20), preds=Array{Int64, (1,)}[2], succs=Array{Int64, (1,)}[4]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=21, last=21), preds=Array{Int64, (1,)}[3], succs=Array{Int64, (1,)}[7]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=22, last=28), preds=Array{Int64, (1,)}[2], succs=Array{Int64, (1,)}[6]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=29, last=29), preds=Array{Int64, (1,)}[5], succs=Array{Int64, (1,)}[7]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=30, last=47), preds=Array{Int64, (2,)}[4, 6], succs=Array{Int64, (2,)}[9, 8]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=48, last=49), preds=Array{Int64, (1,)}[7], succs=Array{Int64, (0,)}[]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=50, last=50), preds=Array{Int64, (1,)}[7], succs=Array{Int64, (1,)}[10]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=51, last=52), preds=Array{Int64, (1,)}[9], succs=Array{Int64, (1,)}[11]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=53, last=53), preds=Array{Int64, (1,)}[10], succs=Array{Int64, (1,)}[12]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=54, last=54), preds=Array{Int64, (1,)}[11], succs=Array{Int64, (1,)}[13]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=55, last=56), preds=Array{Int64, (1,)}[12], succs=Array{Int64, (1,)}[14]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=57, last=65), preds=Array{Int64, (1,)}[13], succs=Array{Int64, (1,)}[15]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=66, last=71), preds=Array{Int64, (1,)}[14], succs=Array{Int64, (2,)}[17, 16]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=72, last=74), preds=Array{Int64, (1,)}[15], succs=Array{Int64, (0,)}[]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=75, last=82), preds=Array{Int64, (1,)}[15], succs=Array{Int64, (2,)}[19, 18]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=83, last=84), preds=Array{Int64, (1,)}[17], succs=Array{Int64, (0,)}[]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=85, last=85), preds=Array{Int64, (1,)}[17], succs=Array{Int64, (1,)}[20]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=86, last=87), preds=Array{Int64, (1,)}[19], succs=Array{Int64, (1,)}[21]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=88, last=88), preds=Array{Int64, (1,)}[20], succs=Array{Int64, (1,)}[22]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=89, last=89), preds=Array{Int64, (1,)}[21], succs=Array{Int64, (1,)}[23]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=90, last=90), preds=Array{Int64, (1,)}[22], succs=Array{Int64, (1,)}[24]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=91, last=92), preds=Array{Int64, (1,)}[23], succs=Array{Int64, (1,)}[25]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=93, last=93), preds=Array{Int64, (1,)}[24], succs=Array{Int64, (1,)}[26]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=94, last=94), preds=Array{Int64, (1,)}[25], succs=Array{Int64, (1,)}[27]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=95, last=95), preds=Array{Int64, (1,)}[26], succs=Array{Int64, (2,)}[29, 28]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=96, last=98), preds=Array{Int64, (1,)}[27], succs=Array{Int64, (0,)}[]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=99, last=102), preds=Array{Int64, (1,)}[27], succs=Array{Int64, (2,)}[31, 30]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=103, last=103), preds=Array{Int64, (1,)}[29], succs=Array{Int64, (1,)}[32]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=104, last=104), preds=Array{Int64, (1,)}[29], succs=Array{Int64, (1,)}[32]),
  Core.Compiler.BasicBlock(stmts=Core.Compiler.StmtRange(first=105, last=107), preds=Array{Int64, (2,)}[30, 31], succs=Array{Int64, (1,)}[1])], i=(0,))
rec_backtrace at /buildworker/worker/package_linux64/build/src/stackwalk.c:94
record_backtrace at /buildworker/worker/package_linux64/build/src/task.c:246
jl_throw at /buildworker/worker/package_linux64/build/src/task.c:577
jl_bounds_error_ints at /buildworker/worker/package_linux64/build/src/rtutils.c:187
getindex at ./array.jl:731
jfptr_getindex_1600.clone_1 at /usr/lib/julia/sys.so (unknown line)
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
replace_code_newstyle! at ./compiler/ssair/legacy.jl:80
optimize at ./compiler/optimize.jl:208
typeinf at ./compiler/typeinfer.jl:35
typeinf_ext at ./compiler/typeinfer.jl:567
typeinf_ext at ./compiler/typeinfer.jl:604
jfptr_typeinf_ext_1.clone_1 at /usr/lib/julia/sys.so (unknown line)
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1536 [inlined]
jl_apply_with_saved_exception_state at /buildworker/worker/package_linux64/build/src/rtutils.c:257
jl_type_infer at /buildworker/worker/package_linux64/build/src/gf.c:275
jl_compile_method_internal at /buildworker/worker/package_linux64/build/src/gf.c:1784 [inlined]
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1828
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1536 [inlined]
start_task at /buildworker/worker/package_linux64/build/src/task.c:268
unknown function (ip: 0xffffffffffffffff)

Does anyone know how to use CuArrays in colab?

I never had this issue. I recently updated the notebook to Julia 1.1 and all worked fine. Here is these updated notebook (Julia 1.1 but still using cuda 9.0):

https://colab.research.google.com/drive/1p0Vo5Uh5ZQo3XSC4y7LNfKLEkXwkpG1-

To get a notebook in Julia, download the following and re-upload in the notebook window where Julia was installed (otherwise you will get an error message that Julia in an unknown language).

https://colab.research.google.com/drive/15eOu-ft5XP2CbR931dHRa-Cr9LwhgkHS

1 Like

hi, i would love to use julia kernel with colab.

I also wish it were possible to embed Colab as a react component

I also wish it were possible to run Colab notebooks offline by transpiling Python/Julia/R/Scala etc into Chromium V8 code … but that might be difficult. Anyone else interested to push Colab into more languages and offline/embedded environments?