Reference Documentation

Parallelism and compute structure

JuliaHub supports fully heterogeneous parallel compute. It uses the Distributed standard library to parallelize across workers on potentially many machines. Each worker can support multiple threads with the builtin Threads module. Each machine can optionally have a computational GPU attached to it for further acceleration with the CUDA package.

All of these modes of operation are fully supported and JuliaHub ensures that all machines in the cluster have the appropriate files and dependencies in place. This means, for example, that you do not need to addprocs or set the number threads yourself; your code should use scale-invariant constructs like pmap, @distributed and @threads or other higher-level abstractions like those for DifferentialEquations.jl.

JuliaHub also scales seamlessly from simple single-file scripts to whole applications with many thousands of lines of code, dependencies (both private and public), binary artifacts, and data. Your IDE will automatically detect all such dependencies, bundle them together, and ensure their availability on every node.

Project, Manifest and Artifacts

When running from VS Code or Juno, these are pre-populated based upon your active project.

When running ad-hoc code, you may choose them manually.

Outputs

Set ENV["RESULTS"] to contain a simple JSON string to display certain values in the Output table. This is helpful for a handful of summary values to compare jobs at a glance on JuliaHub through the Details button. The contents of ENV["RESULTS"] are restricted to 1000 characters. If a longer value is set, it will be truncated.

You can further set the ENV["RESULTS_FILE"] to a local file on the filesystem that will be available for download after job completion. While there is only one results file per job, note that you can zip or tar multiple files together. The overall size of the results (the single file or the tar bundle) is limited to 5GiB. Upload of result exceeding that size is would fail, and they will not be available for download later.

Cluster design

Choose the number of cores and machines as appropriate:

Cluster design

Select the node type that you wish to use. Node types determine the vCPU, memory, and type of GPU available on each node.

It is possible to either start a job with single Julia process or with multiple Julia processes.

  • To start a job with single Julia process, select single-process for "Mode".
  • To start a job with multiple Julia processes, select distributed for "Mode".

The vCPU and memory selections will determine the node type/size on which the job will be run.

The actual number of Julia processes that will be started depends on the selection for processes per node and number of nodes, such that total number of Julia processes = number of nodes * processes per node.

Note that one Julia process will always be designated to be the master and the remaining would be worker processes.

Elastic worker pool

The worker pool type of a distributed job can be one of fixed or elastic.

  • A job with fixed worker pool would wait for all (or a configured minimum) number of workers to join before the job code is executed. Once the job code starts executing, no more (delayed) workers are allowed to join. Also if any worker fails during execution it would not be restarted.

  • A job with an elastic worker pool would not wait for workers before starting to execute the job code. But it would allow workers to join any time while the job code is running. And if any worker fails during execution they would be restarted.

Elastic worker pools

An elastic worker pool has the advantage of quick start times and is resilient to failures. However they may not be suitable for all types of programs.

Programs that do not depend on workers being initialized in a specific way should already be compatible to the elastic mode. The only change that they may need is where the code needs a certain minimum number of workers to work, they may need to add a check. E.g.:

using Distributed

@assert :ok === timedwait(120.0; pollint=5.0) do
    nworkers() >= min_workers_required
end

Programs that require specific initialization steps to be done on the worker, typically done via one or more @everywhere macro invocations in the beginning, can be adapted to be elastic mode compatible using certain (experimental) APIs provided in the JuliaHub environment. Essentially it involves using the @init_workers macro provided in the JuliaRunJob.Elastic module instead of @everywhere. E.g.:

using Main.JuliaRunJob.Elastic
 
Elastic.@init_workers begin
    function docalc(x)
        # ...
        x*10
    end
end

If the program makes use of pmap, use the one provided in the JuliaRunJob.Elastic module instead. E.g.:

Elastic.pmap(a) do x
    return docalc(x)
end

Other Distributed APIs that accept a worker pool can also be used, by explicitly providing the elastic pool instance. The Elastic.pool() API provides a reference to the elastic worker pool.

Logging

While running your job, live logs are available. Note that it can take a few minutes to launch the machines (longer for GPU machines). The logs are searchable through dynamic filters, with additional information available if you use the builtin [logging] module and related macros (like @info, @warn, and friends).

Preferences and Payments

The "Preferences" and "Payments" pages for the account can be accessed by clicking on the account settings icon in the upper right corner of the screen.

Open Preferences Page

The menu can also be used to toggle between a light and dark theme for the web interface.

Secrets

Jobs can have access to secrets. Secrets can store sensitive information encrypted and make them available to your job at run time. This is available for use only in batch jobs as of now.

Secrets can be configured on the account preferences page. The secrets management section will list existing secrets if any are configured.

Secrets are associated with namespaces. The default namespace of a regular user is the email id with which they logged in. One may see other namespaces corresponding to groups that they belong to. A secret created with a group namespace is accessible to all users who belong to that group. Note that group members will have both read and write access to secrets in the group.

Add or Delete Secret

In the Job environment, secrets from the user's own namespace can be accessed in jobs using the intuitive get_secret API: secretvalue = JuliaRunJob.get_secret(secretname).

There is also a secrets manager get API that can be used to access secrets from other namespaces a user may have access to when the user belongs to any group:

secretvalue = JuliaRunJob.get(
        JuliaRunJob.SECRETS_MANAGER[],
        joinpath(base64encode(secrets_namespace), secretname)
    )

Where:

  • SECRETS_MANAGER[] provides a handle to the secrets manager context for the job
  • secretname is the name of the secret to access
  • secrets_namespace is the namespace in which the secret exists

It is important to note that these APIs are currently not supported for Julia IDE jobs, thus they cannot be called in VS Code. Users can use these APIs in Julia code, which can then be submitted as input for Standard Batch jobs.

Billing

Set your credit card information in the Payments settings:

Setting CC info

Billing is done at per-second interval, but with a minimum 10 minutes per job. You may set the maximum time or cost for any given job, but note that jobs that exceed that limit will be killed without storing any outputs (although logs will still be available).

Authentication

In order to communicate with the JuliaHub backend servers (e.g. to access datasets), a Julia session must have access to a user-specific authentication token. For this, JuliaHub reuses Julia's built-in support for authenticating with a package server.

In order for this to work, Julia must be configured to use the JuliaHub package server, and an auth.toml file, containing the user-specific authentication token, must be present in the ~/.julia directory.

In the different JuliaHub applications, this is generally all set up automatically. However, to access JuliaHub from external machines, this can be configured manually by

  1. Downloading the auth.toml file from the preference page on JuliaHub and saving it to .julia/servers/juliahub.com/auth.toml.

Authentication Token Download

  1. Configuring Julia to use the JuliaHub package server at https://juliahub.com/ (e.g. by setting JULIA_PKG_SERVER as JULIA_PKG_SERVER="https://juliahub.com/", or directly in the JuliaHub VSCode IDE plugin).

Note that the token in auth.toml expires in 24 hours if it is not used, and must be downloaded again. However, any operation in the Julia package manager that talks to the package server (like updating a package or the registry) will refresh the token automatically.

Connecting VSCode IDE to JuliaHub

Make sure you've got the main Julia plugin installed from the VSCode marketplace as discussed in the vscode Julia extension documentation.

Next, install the JuliaHub plugin from the VSCode marketplace. Once installed, use the "show JuliaHub" command to open the JuliaHub pane.

The JuliaHub plugin uses the package server setting from the Julia plugin. You'll need to set this to https://juliahub.com:

juliahub package setting

If need be, the VSCode plugin will open a browser window to authenticate with JuliaHub and then automatically acquire the auth.toml file.