Julia on Google Colab: Free GPU-Accelerated Shareable Notebooks

Thanks for your kind words, Steven. I implemented your suggestions.

1 Like

Hello,

This is great work!

I just tried the template and updated to Julia verson 1.5.0. Running the first cell generated the

Unrecognized runtime “julia”; defaulting to “python3” Notebook settings

but the template appears to work, however.

Success! Please reload this page and jump to the next section.

Julia Version 1.5.0
Commit 96786e22cc (2020-08-01 23:44 UTC)
Platform Info:
** OS: Linux (x86_64-pc-linux-gnu)**
** CPU: Intel(R) Xeon(R) CPU @ 2.20GHz**
** WORD_SIZE: 64**
** LIBM: libopenlibm**
** LLVM: libLLVM-9.0.1 (ORCJIT, broadwell)**
Environment:
** JULIA_NUM_THREADS = 2**

Per instructions, I understand that we should run the template’s first cell in each new cola notebook.

Thanks

2 Likes

Using Julia on google colab via SSH with vscode server

“Run VS Code on any machine anywhere and access it in the browser.” code-server

Please let me know if you have any suggestions for improving the script!

2 Likes

So this is another version agnostic solution I just came up with:
https://github.com/johnnychen94/colab-julia-bootstrap

No major functionality difference to ageron’s template but I guess more readable because it’s much shorter :grinning_face_with_smiling_eyes:

4 Likes

Thanks all for this hack. I manage to run Julia on Google Colab. However, I cannot find a way to mount Google Drive to use with Julia (on Google Colab). I tried using PyCall like this:

using PyCall
googleDrive = pyimport("google.colab.drive")
googleDrive.mount("/content/drive")

but it gives the following error:

Go to this URL in a browser: https://accounts.google.com/o/oauth2/auth?client_id=947318989803-6bn6qk8qdgf4n4g3pfee6491hc0brc4i.apps.googleusercontent.com&redirect_uri=urn%3aietf%3awg%3aoauth%3a2.0%3aoob&scope=email%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdocs.test%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.photos.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fpeopleapi.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fdrive.activity.readonly%20https%3a%2f%2fwww.googleapis.com%2fauth%2fexperimentsandconfigs%20https%3a%2f%2fwww.googleapis.com%2fauth%2fphotos.native&response_type=code

Enter your authorization code:
PyError ($(Expr(:escape, :(ccall(#= /root/.julia/packages/PyCall/BD546/src/pyfncall.jl:43 =# @pysym(:PyObject_Call), PyPtr, (PyPtr, PyPtr, PyPtr), o, pyargsptr, kw))))) <class 'EOFError'>
EOFError('EOF when reading a line')
  File "/usr/local/lib/python3.7/dist-packages/google/colab/drive.py", line 260, in mount
    fifo_file.write(get_code(auth_prompt) + '\n')

Switching the runtime type to “Python” to mount Google Drive will just get rid of the “julia” runtime of the notebook.

Any idea is appreciated!

1 Like

@JohnnyChen94 is your repo for installing Julia on Colab working fine with Julia v1.6.2? I never used Colab before but apparently I can’t load any package after Julia is installed and the package is installed with Pkg.jl. For example, doing a simple Pkg.add("CSV") will install an old version of CSV.jl. I then force the installation of the latest version with Pkg.add(name="CSV", version="0.8.5") but when I try to using CSV in another cell I get load errors.

Any help is appreciated as we are doing a workshop this week and participants with less-powerful machines need a Colab instance to contribute more efficiently.

I don’t see any issues with my setup script.

For example, doing a simple Pkg.add("CSV") will install an old version of CSV.jl. I then force the installation of the latest version with Pkg.add(name="CSV", version="0.8.5") but when I try to using CSV in another cell I get load errors.

The only dependency that the notebook requires is IJulia, so if there are some version conflicts with IJulia, then this could happen. But I guess a refresh of the notebook page Ctrl-R or restarting kernels could resolve the issues.

For this very specific case and time point, I believe it’s because CSV hasn’t yet released a version compatible with Parsers@2; CSV@0.8.5 is compatible with Parsers@1 only

1 Like

Thank you @JohnnyChen94 , it is good to know that this is not an issue with the Colab setup. I think we are stuck due to the CSV.jl compatibility issue. They recently released CSV.jl v0.9 but until it propagates in others Project.toml the workshop will be done.

First, thanks for this!

I managed to get it up and running with Julia GPU (CUDA) and it worked as expected.

However, there is one “issue”: selecting GPU backend seems to start a new runtime which puts python back. Adding Julia to this new runtime needs a refresh at the end of the procedure which switches backend back to CPU. Is there any fix you could suggest for escaping this circular reasoning ? Thanks.

2 Likes

A good catch, I admit that I didn’t experiment with the CUDA stuff when I posted it. It seems that instead of refreshing the page via “Ctrl-R”, you’ll have to manually reload the kernel via

  1. go to “view resources” → “change runtime type”
  2. ensure it is “Julia” and “GPU”. Almost certainly you don’t need to change anything here if you’re already on GPU runtime.
  3. click “save” to trigger the kernel reload.

FWIW, I uploaded a new julia_cuda.ipynb file to smooth this progress.

2 Likes

Thanks for the update.

However, I run in another issue now. It seems that running “your” notebook works fine as upon refresh, Julia runtime is available (and auto selected). However, following fails:

  1. starting a blank new colab notebook
  2. pasting the first cell content (CPU version)
  3. executing it
  4. refreshing (cmd+r or change-runtime)
  5. getting stuck in the python kernel

EDIT: Thanks @psanan - that was the missing bit.

One has to save a copy of the provided notebook, because there is extra metadata in the .ipynb file (not directly visible unless you look at the raw file). E.g. from here

...
"metadata": {
   ...
    "kernelspec": {
      "display_name": "Julia",
      "name": "julia"
    }
  },
 ...
1 Like

Is this still working for GPU?
I used this ipynb to successfully install CUDA, but when I tested it, I always got the following:

a = CUDA.ones(2,3)

CUDA error: unknown error (code 999, ERROR_UNKNOWN)


Stacktrace:

  [1] throw_api_error(res::CUDA.cudaError_enum)

    @ CUDA ~/.julia/packages/CUDA/bki2w/lib/cudadrv/error.jl:91

  [2] macro expansion

    @ ~/.julia/packages/CUDA/bki2w/lib/cudadrv/error.jl:101 [inlined]

  [3] cuDevicePrimaryCtxRetain

    @ ~/.julia/packages/CUDA/bki2w/lib/utils/call.jl:26 [inlined]

  [4] CuContext

    @ ~/.julia/packages/CUDA/bki2w/lib/cudadrv/context.jl:55 [inlined]

  [5] context(dev::CuDevice)

    @ CUDA ~/.julia/packages/CUDA/bki2w/lib/cudadrv/state.jl:222

  [6] TaskLocalState (repeats 2 times)

    @ ~/.julia/packages/CUDA/bki2w/lib/cudadrv/state.jl:50 [inlined]

  [7] task_local_state!()

    @ CUDA ~/.julia/packages/CUDA/bki2w/lib/cudadrv/state.jl:73

  [8] active_state

    @ ~/.julia/packages/CUDA/bki2w/lib/cudadrv/state.jl:106 [inlined]

  [9] #_alloc#192

    @ ~/.julia/packages/CUDA/bki2w/src/pool.jl:179 [inlined]

 [10] #alloc#191

    @ ~/.julia/packages/CUDA/bki2w/src/pool.jl:169 [inlined]

 [11] alloc

    @ ~/.julia/packages/CUDA/bki2w/src/pool.jl:165 [inlined]

 [12] CuArray{Float32, 2, CUDA.Mem.DeviceBuffer}(#unused#::UndefInitializer, dims::Tuple{Int64, Int64})

    @ CUDA ~/.julia/packages/CUDA/bki2w/src/array.jl:44

 [13] CuArray

    @ ~/.julia/packages/CUDA/bki2w/src/array.jl:125 [inlined]

 [14] CuArray

    @ ~/.julia/packages/CUDA/bki2w/src/array.jl:136 [inlined]

 [15] CuArray

    @ ~/.julia/packages/CUDA/bki2w/src/array.jl:138 [inlined]

 [16] ones

    @ ~/.julia/packages/CUDA/bki2w/src/array.jl:552 [inlined]

 [17] ones(::Int64, ::Int64)

    @ CUDA ~/.julia/packages/CUDA/bki2w/src/array.jl:554

 [18] top-level scope

    @ In[3]:1

 [19] eval

    @ ./boot.jl:373 [inlined]

 [20] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)

    @ Base ./loading.jl:1196

It seems that colab has some special device and version environment that CUDA.jl fails to support. Maybe @maleadt knows what happens here.

1 Like

Looks like Colab’s environment doesn’t play well with NVIDIA’s forward-compatible driver. You can disable this by setting the environment variable JULIA_CUDA_USE_COMPAT to false, e.g., doing ENV["JULIA_CUDA_USE_COMPAT"] = "false" before using CUDA. That makes it work for me.

Maybe @jekbradbury knows why this isn’t supported?

Also note CUDA.jl nowadays doesn’t need a locally-installed CUDA anymore, so the instructions can be simplified to:

!curl -sSL "https://julialang-s3.julialang.org/bin/linux/x64/1.7/julia-1.7.2-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 CUDA; precompile"'
5 Likes

Thank you! It now works for me.

I encountered a new problem: any operation results in an error message "“CUDA error: operation not supported (code 801, ERROR_NOT_SUPPORTED)”. For example,
CuArray{Int}(undef, 2)
results in

CUDA error: operation not supported (code 801, ERROR_NOT_SUPPORTED)


Stacktrace:

  [1] throw_api_error(res::CUDA.cudaError_enum)

    @ CUDA ~/.julia/packages/CUDA/KnJGx/lib/cudadrv/error.jl:91

  [2] macro expansion

    @ ~/.julia/packages/CUDA/KnJGx/lib/cudadrv/error.jl:101 [inlined]

  [3] cuMemAllocAsync(dptr::Base.RefValue{CuPtr{Nothing}}, bytesize::Int64, hStream::CuStream)

    @ CUDA ~/.julia/packages/CUDA/KnJGx/lib/utils/call.jl:26

  [4] #alloc#1

    @ ~/.julia/packages/CUDA/KnJGx/lib/cudadrv/memory.jl:83 [inlined]

  [5] macro expansion

    @ ~/.julia/packages/CUDA/KnJGx/src/pool.jl:41 [inlined]

  [6] macro expansion

    @ ./timing.jl:299 [inlined]

  [7] actual_alloc(bytes::Int64; async::Bool, stream::CuStream)

    @ CUDA ~/.julia/packages/CUDA/KnJGx/src/pool.jl:39

  [8] macro expansion

    @ ~/.julia/packages/CUDA/KnJGx/src/pool.jl:173 [inlined]

  [9] macro expansion

    @ ./timing.jl:299 [inlined]

 [10] #_alloc#198

    @ ~/.julia/packages/CUDA/KnJGx/src/pool.jl:254 [inlined]

 [11] #alloc#197

    @ ~/.julia/packages/CUDA/KnJGx/src/pool.jl:240 [inlined]

 [12] alloc

    @ ~/.julia/packages/CUDA/KnJGx/src/pool.jl:236 [inlined]

 [13] CuArray

    @ ~/.julia/packages/CUDA/KnJGx/src/array.jl:42 [inlined]

 [14] CuArray

    @ ~/.julia/packages/CUDA/KnJGx/src/array.jl:125 [inlined]

 [15] CuArray

    @ ~/.julia/packages/CUDA/KnJGx/src/array.jl:136 [inlined]

 [16] (CuArray{Int64})(#unused#::UndefInitializer, dims::Int64)

    @ CUDA ~/.julia/packages/CUDA/KnJGx/src/array.jl:138

 [17] top-level scope

    @ In[2]:1

 [18] eval

    @ ./boot.jl:373 [inlined]

 [19] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)

    @ Base ./loading.jl:1196

However, the version info can be shown by

ENV["JULIA_CUDA_USE_BINARYBUILDER"] = false
ENV["JULIA_CUDA_USE_COMPAT"] = "false"

using CUDA
CUDA.versioninfo()

as

CUDA toolkit 11.1, local installation
NVIDIA driver 460.32.3, for CUDA 11.2
CUDA driver 11.2

Libraries: 
- CUBLAS: 11.3.0
- CURAND: 10.2.2
- CUFFT: 10.3.0
- CUSOLVER: 11.0.1
- CUSPARSE: 11.3.0
- CUPTI: 14.0.0
- NVML: 11.0.0+460.32.3
- CUDNN: 7.60.5 (for CUDA 10.1.0)
- CUTENSOR: missing

Toolchain:
- Julia: 1.7.2
- LLVM: 12.0.1
- PTX ISA support: 3.2, 4.0, 4.1, 4.2, 4.3, 5.0, 6.0, 6.1, 6.3, 6.4, 6.5, 7.0
- Device capability support: sm_35, sm_37, sm_50, sm_52, sm_53, sm_60, sm_61, sm_62, sm_70, sm_72, sm_75, sm_80

Environment:
- JULIA_CUDA_USE_BINARYBUILDER: false
- JULIA_CUDA_USE_COMPAT: false

1 device:
  0: Tesla K80 (sm_37, 11.170 GiB / 11.173 GiB available)

┌ Warning: This version of CUDA.jl only supports CUDNN 8.0 or higher
└ @ CUDA.CUDNN /root/.julia/packages/CUDA/KnJGx/lib/cudnn/CUDNN.jl:149

What should I do? Thanks.

Hi @photor, I was able to get Google Colab’s to run that command:

I followed the steps that @ageron mentioned in his Colab notebook template, and ran the following cells:

%%shell

set -e

#---------------------------------------------------#

JULIA_VERSION="1.7.2" # For any version ≄ 0.7.0

                      # As of 2022.03.05, latest stable release is 1.7.2

JULIA_PACKAGES="IJulia BenchmarkTools Plots Flux" 

                                  # Installs any preferred packages.

                                  # Separate by space, no need for the `.jl`

                                  # extension.

JULIA_PACKAGES_IF_GPU="CUDA" # Or use CuArrays for older Julia versions.

JULIA_NUM_THREADS=4 # Sets number of tasks for concurrency or parallelism.

#---------------------------------------------------#

if [ -n "$COLAB_GPU" ] && [ -z `which julia` ]; then

  # Install Julia

  JULIA_VER=`cut -d '.' -f -2 <<< "$JULIA_VERSION"`

  echo "Installing Julia $JULIA_VERSION on the current Colab Runtime..."

  BASE_URL="https://julialang-s3.julialang.org/bin/linux/x64"

  URL="$BASE_URL/$JULIA_VER/julia-$JULIA_VERSION-linux-x86_64.tar.gz"

  wget -nv $URL -O /tmp/julia.tar.gz # -nv means "not verbose"

  tar -x -f /tmp/julia.tar.gz -C /usr/local --strip-components 1

  rm /tmp/julia.tar.gz

  # Install Packages

  if [ "$COLAB_GPU" = "1" ]; then

      JULIA_PACKAGES="$JULIA_PACKAGES $JULIA_PACKAGES_IF_GPU"

  fi

  for PKG in `echo $JULIA_PACKAGES`; do

    echo "Installing Julia package $PKG..."

    julia -e 'using Pkg; pkg"add '$PKG'; precompile;"' &> /dev/null

  done

  # Install kernel and rename it to "julia"

  echo "Installing IJulia kernel..."

  julia -e 'using IJulia; IJulia.installkernel("julia", env=Dict(

      "JULIA_NUM_THREADS"=>"'"$JULIA_NUM_THREADS"'"))'

  KERNEL_DIR=`julia -e "using IJulia; print(IJulia.kerneldir())"`

  KERNEL_NAME=`ls -d "$KERNEL_DIR"/julia*`

  mv -f $KERNEL_NAME "$KERNEL_DIR"/julia  

  echo ''

  echo "Successfully installed `julia -v`!"

  echo "Please reload this page (press Ctrl+R, ⌘+R, or the F5 key) then"

  echo "jump to the 'Checking the Installation' section."

fi

The only thing I changed from his notebook template was updating the Julia version to 1.7.2 and increased the thread count from 2 to 4. I also ran the cells

versioninfo()

and

if ENV["COLAB_GPU"] == "1"
    using CUDA

    run(`nvidia-smi`)

    # Create a new random matrix directly on the GPU:
    M_on_gpu = CUDA.CURAND.rand(2^11, 2^11)
    @btime $M_on_gpu * $M_on_gpu; nothing
else
    println("No GPU found.")
end

to make sure CUDA was working with the GPU hardware acceleration. Then I ran CuArray{Int}(undef, 2) and got the expected output. Hope that helps! ^.^

2 Likes

Upgrade CUDA.jl; this is a bug which has been fixed.

1 Like