Hyppää sisältöön

Docs CSC now features an automatic Finnish translation. Click here for more information.

Warning!

Puhti and Mahti are being decommissioned in stages, and their storage areas will become fully unavailable from 15 October 2026. Clean up unnecessary files and move any data you need to keep by 31 August 2026. See the Roihu data migration guide for instructions on transferring your data to Roihu.

Puhti scratch is very full: keep only active data there and move or delete everything else. No new Puhti scratch quota will be granted.

Julia-ohjelmointikieli

Julia-ohjelmointikieli on suorituskykyinen, dynaaminen ohjelmointikieli. Julia soveltuu erinomaisesti tieteelliseen laskentaan, koska se pystyy kääntämään tehokasta natiivikoodia LLVM:n avulla ja sisältää standardikirjastossa matemaattisia funktioita, rinnakkaislaskentaominaisuuksia sekä paketinhallinnan. Lisäksi Julian syntaksi on intuitiivinen ja helppo oppia, multiple-dispatch-paradigma mahdollistaa koostettavan koodin kirjoittamisen, mikä lisää olemassa olevan koodin uudelleenkäytettävyyttä, ja ympäristöt mahdollistavat koodin suorittamisen toistettavalla tavalla.

Lisenssi

Julia-ohjelmointikieli on lisensoitu vapaalla ja avoimen lähdekoodin MIT-lisenssillä.

Viittaaminen

Jos käytät Juliaa tutkimuksessasi, viittaa seuraavaan artikkeliin:

Jeff Bezanson, Alan Edelman, Stefan Karpinski, and Viral B. Shah (2017). Julia: A Fresh Approach to Numerical Computing. SIAM Review, 59(1), 65–98. DOI: 10.1137/141000671

Jos haluat löytää oikean viittauksen tietylle Julia-paketille, voit käyttää komentoa pkg> status tai tutustua paketin dokumentaatioon ja repositorioon.

Saatavuus

Julia-ohjelmointikieli on käytettävissä Roihu-CPU:ssa, Roihu-GPU:ssa, Mahdissa ja LUMIssa komentorivikäyttöliittymästä moduulijärjestelmän kautta. Se on käytettävissä myös selainkäyttöliittymässä Jupyterin ja VSCoden kautta.

Jos kohtaat ongelmia Julian käytössä klusterissa, sinun kannattaa ottaa yhteyttä servicedeskiin.

Käyttö

Julia-moduulin käyttäminen

Julia-ohjelmointikieli on saatavilla julia-moduulista.

Roihu-CPU:ssa, Roihu-GPU:ssa ja Mahdissa moduuli voidaan ladata seuraavasti:

module load julia

LUMIssa meidän täytyy lisätä CSC:n paikallisen hakemiston moduulitiedostot moduulipolkuun ennen moduulin lataamista.

module use /appl/local/csc/modulefiles
module load julia

Julia-moduulin lataamisen jälkeen voimme käyttää Juliaa komennolla julia. Ilman argumentteja se käynnistää interaktiivisen Julia-REPL:n.

julia

Saatavilla olevat komentorivivalinnat näet komennolla julia --help tai lukemalla manuaalisivun man julia. Jos sinulla on kysymyksiä Julia-ohjelmointikielen ominaisuuksista, suosittelemme virallista dokumentaatiota ja Discourse -kanavaa.

Paketinhallinnan käyttäminen

Vakiotapa asentaa Julia-paketteja on käyttää standardikirjaston paketinhallintaa Pkg. Juliassa se voidaan tuoda käyttöön seuraavasti:

import Pkg

Yleisiä käyttämiämme toimintoja ovat Pkg.add pakettien lisäämiseen, Pkg.activate ympäristöjen aktivointiin ja Pkg.instantiate kaikkien aktiivisessa ympäristössä määriteltyjen pakettien asentamiseen. Pdokumentaatio sisältää lisätietoa Julian paketinhallinnan käytöstä.

Julia depot -hakemiston sijoittaminen

Julia depot -polun ensimmäinen hakemisto määrittää, minne Julia tallentaa asennetut paketit, käännetyt tiedostot, lokitiedostot ja muut depotit. Oletusarvoisesti se on $HOME/.julia. Kotihakemistolla on suhteellisen pieni kiintiö Roihussa, Mahdissa ja LUMIssa. Jos asennat suuria paketteja, suosittelemme sijoittamaan depot-hakemiston Projapplin alle, jotta kiintiö ei lopu kesken. Voimme vaihtaa depot-hakemiston lisäämällä uuden hakemiston ympäristömuuttujan JULIA_DEPOT_PATH alkuun.

Voimme esimerkiksi käyttää seuraavaa korvaamalla <project> CSC-projektilla.

export JULIA_DEPOT_PATH="/projappl/<project>/$USER/.julia:$JULIA_DEPOT_PATH"

Tämän jälkeen voit turvallisesti poistaa oletus-depot-hakemiston komennolla rm -r $HOME/.julia. Lisätietoa löytyy depot path -dokumentaatiosta.

Monisäikeisyys

Julia tarjoaa Threads-kirjaston monisäikeisyyteen. Se sisältyy peruskirjastoon ja tuodaan oletuksena käyttöön Julia-istunnossa. Voimme käynnistää Julian usealla säikeellä asettamalla ympäristömuuttujan JULIA_NUM_THREADS tai käynnistämällä Julian valinnalla --threads, joka ohittaa ympäristömuuttujan arvon. Jos Julia-moduuli on ladattu Slurm-työssä eikä ympäristömuuttujaa ole asetettu, sen arvoksi asetetaan pyydettyjen CPU-ytimien määrä (--cpus-per-task). Säikeiden oletusmäärä on yksi. Suosittelemme lukemaan Julian manuaalin monisäikeisyys -osion lisätietoja varten.

Moniprosessointi ja hajautettu laskenta

Distributed ja SlurmClusterManager.jl

Moniprosessointiin ja hajautettuun laskentaan Julia tarjoaa Distributed-standardikirjaston. Käytämme sitä moniprosessointiin paikallisella solmulla. Voimme laajentaa Distributed-kirjastoa asentamalla SlurmClusterManager.jl-paketin, jonka avulla voimme lisätä työprosessit useille solmuille Slurmin kautta käyttäen SlurmManager-hallintaa. Suosittelemme lukemaan Julian manuaalin moniprosessointi ja hajautettu laskenta -osion lisätietoja varten.

MPI.jl

Voimme käyttää MPI:tä hajautettuun laskentaan, erityisesti useiden solmujen yli, Juliassa Roihu-CPU:ssa, Roihu-GPU:ssa, Mahdissa ja LUMIssa MPI.jl-paketin avulla. Voimme asentaa sen paketinhallinnalla seuraavasti:

import Pkg
Pkg.add("MPI")

Voimme ladata julia-mpi-moduulin, joka asettaa ympäristöön globaalit asetukset niin, että MPI.jl käyttää järjestelmän MPI-asennusta ja oikeaa komentoa MPI-prosessien käynnistämiseen.

module load julia-mpi

Lisätietoja varten suosittelemme lukemaan MPI.jl-dokumentaation.

GPU-ohjelmointi

CUDA.jl

Roihu-GPU:n ja Mahdin GPU-solmut sisältävät NVidia-GPU:ita, joita voidaan ohjelmoida CUDA:n avulla. Voimme asentaa CUDA.jl-paketin CUDA-ohjelmointia varten Juliassa paketinhallinnalla seuraavasti:

import Pkg
Pkg.add("CUDA")

Voimme ladata julia-cuda-moduulin, joka asettaa ympäristöön globaalit asetukset niin, että CUDA.jl käyttää järjestelmän CUDA-asennusta.

module load julia-cuda

Lisätietoja varten suosittelemme lukemaan CUDA.jl-dokumentaation.

AMDGPU.jl

LUMIn GPU-solmut sisältävät AMD-GPU:ita. Voimme asentaa AMDGPU.jl-paketin AMD-GPU:iden ohjelmointia varten Juliassa paketinhallinnalla seuraavasti:

import Pkg
Pkg.add("AMDGPU")

Voimme ladata julia-amdgpu-moduulin, joka asettaa ympäristöön globaalit asetukset niin, että AMDGPU.jl käyttää järjestelmän ROCm-asennusta.

module load julia-amdgpu

Lisätietoja varten suosittelemme lukemaan AMDGPU.jl-dokumentaation.

Lisälukemista

Jos haluat lukea lisää rinnakkais- ja suorituskykylaskennasta Julian avulla, suosittelemme ENCCS:n materiaalia Julia for high-performance scientific computing sekä Kjartan Thor Wikfeldtin kirjoitusta A brief tour of Julia for high-performance computing. HLRS:n koulutusmateriaali kurssille Julia for High-Performance Computing tarjoaa syvällisen katsauksen suorituskykyisen koodin ohjelmointiin Julian avulla. Lopuksi Julia on HPC Clusters listaa yleisiä huomioita Julian käytöstä ja asentamisesta HPC-klusterissa.

Julia-eräajojen suorittaminen CSC:n klustereissa

Tämä osio sisältää esimerkkejä erilaisten Julia-eräajojen suorittamisesta Roihu-CPU-, Roihu-GPU-, Mahti- ja LUMI-klustereissa. Ne havainnollistavat yllä kuvatun Julia-ympäristön käyttöä erilaisissa eräajoissa. Ne on mukautettu yleisistä ohjeista töiden ajamiseen Roihussa ja Mahdissa sekä LUMIssa. Huomaa, että emme käytä srun-komentoa prosessien käynnistämiseen eräajokomentosarjassa. Sen sijaan käytämme Juliaa prosessien hallintaan tai kutsumme srun-komentoa Julia-koodin sisältä.

Ennen esimerkkien ajamista meidän täytyy instansioida Julia-projekti kirjautumissolmulla. Toisin sanoen suorita seuraava komento siinä hakemistossa, jossa Julia-ympäristösi sijaitsee ja jossa Project.toml-tiedosto on.

module purge
module load julia
julia --project=. --threads=1 -e 'using Pkg; Pkg.instantiate()'
module load julia
julia --project=. --threads=1 -e 'using Pkg; Pkg.instantiate()'
module use /appl/local/csc/modulefiles
module load julia
julia --project=. --threads=1 -e 'using Pkg; Pkg.instantiate()'

Voit käyttää useita säikeitä --threads=10, mikä nopeuttaa esikäännöstä.

Sarjaohjelma

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
└── script.jl     # Julia script
script.jl
println("Hello world!")
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=1000

module purge
module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=interactive
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=1875

module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=1000

module use /appl/local/csc/modulefiles
module load julia
julia --project=. script.jl

Monisäikeisyys yhdellä solmulla

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
└── script.jl     # Julia script
script.jl
# Number of threads
n = Threads.nthreads()
println(n)

# Lets fill the id of each thread to the ids array.
ids = zeros(Int, n)
Threads.@threads for i in eachindex(ids)
    ids[i] = Threads.threadid()
end
println(ids)

# Alternatively, we can use the @spawn macro to run task on threads.
ids = zeros(Int, n)
@sync for i in eachindex(ids)
    Threads.@spawn ids[i] = Threads.threadid()
end
println(ids)
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=3
#SBATCH --mem-per-cpu=1000

module purge
module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=medium
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=128
#SBATCH --mem-per-cpu=0

module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=3
#SBATCH --mem-per-cpu=1000

module use /appl/local/csc/modulefiles
module load julia
julia --project=. script.jl

Moniprosessointi yhdellä solmulla

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
└── script.jl     # Julia script
Project.toml
[deps]
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
script.jl
using Distributed

# We set one worker process per core.
proc_num = Sys.CPU_THREADS

# Environment variables that we pass to the worker processes.
# We set the thread count to one since each process uses one core.
proc_env = [
    "JULIA_NUM_THREADS"=>"1",
    "JULIA_CPU_THREADS"=>"1",
    "OPENBLAS_NUM_THREADS"=>"1",
]

# We add worker processes to the local node using LocalManager.
addprocs(proc_num; env=proc_env, exeflags="--project=.")

# We use the `@everywhere` macro to include the task function in the worker processes.
# We must call `@everywhere` after adding worker processes; otherwise the code won't be included in the new processes.
@everywhere function task()
    return (worker=myid(), hostname=gethostname(), pid=getpid())
end

# We run the task function in each worker process.
futures = [@spawnat worker task() for worker in workers()]

# Then, we fetch the output from the processes.
outputs = fetch.(futures)

# Remove processes after we are done.
rmprocs.(workers())

# Print the outputs of master and worker processes.
println(task())
println.(outputs)
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=3
#SBATCH --mem-per-cpu=1000

module purge
module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=medium
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=128
#SBATCH --mem-per-cpu=0

module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=3
#SBATCH --mem-per-cpu=1000

module use /appl/local/csc/modulefiles
module load julia
julia --project=. script.jl

Moniprosessointi useilla solmuilla

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
└── script.jl     # Julia script
Project.toml
[deps]
SlurmClusterManager = "c82cd089-7bf7-41d7-976b-6b5d413cbe0a"
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
script.jl
using Distributed
using SlurmClusterManager

# Environment variables that we pass to the worker processes.
# We set the thread count to one since each process uses one core.
n = get(ENV, "SLURM_CPUS_PER_TASK", "1")
proc_env = [
    "JULIA_NUM_THREADS"=>"$n",
    "JULIA_CPU_THREADS"=>"$n",
    "OPENBLAS_NUM_THREADS"=>"$n",
]

# We add worker processes across the allocated nodes using SlurmManager
manager = SlurmManager(; launch_timeout=300)
addprocs(manager; env=proc_env, exeflags="--project=.")

# We use the `@everywhere` macro to include the task function in the worker processes.
# We must call `@everywhere` after adding worker processes; otherwise the code won't be included in the new processes.
@everywhere function task()
    return (worker=myid(), hostname=gethostname(), pid=getpid())
end

# We run the task function in each worker process.
futures = [@spawnat worker task() for worker in workers()]

# Then, we fetch the output from the processes.
outputs = fetch.(futures)

# Remove processes after we are done.
rmprocs.(workers())

# Print the outputs of master and worker processes.
println(task())
println.(outputs)
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=medium
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=384
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=1000

module purge
module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=medium
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=128
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=0

module load julia
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=standard
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=128
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=0

module use /appl/local/csc/modulefiles
module load julia
julia --project=. script.jl

MPI-ohjelma

Käynnistämme MPI-ohjelman Julian mpiexec-wrapper-funktion avulla. Wrapper-funktio korvaa paikallisista asetuksista oikean komennon mpirun-muuttujaan MPI-ohjelman suorittamista varten. Komento on srun Roihussa, Mahdissa ja LUMIssa. Wrapperin avulla voimme kirjoittaa joustavampaa koodia, esimerkiksi yhdistää MPI- ja ei-MPI-koodia, sekä siirrettävämpää koodia, koska MPI-ohjelmien suorituskomento voi vaihdella eri alustoilla. Huomaa, että laajamittaisissa Julia MPI -ajoissa, joissa on tuhansia rankeja, meidän täytyy jakaa depot-hakemisto paikallisen solmun tallennustilaan tai muistiin ja muokata depot-poluja vastaavasti. Muuten pakettien lataamisesta tulee erittäin hidasta.

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
├── prog.jl       # Julia MPI program
└── script.jl     # Julia script
Project.toml
[deps]
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
script.jl
using MPI
mpiexec(mpirun -> run(`$mpirun julia --project=. prog.jl`))
prog.jl
using MPI

MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
size = MPI.Comm_size(comm)
println("Hello from rank $(rank) out of $(size) from host $(gethostname()) and process $(getpid()).")
MPI.Barrier(comm)
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=medium
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=384
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=1000

module purge
module load julia
module load julia-mpi
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=medium
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=128
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=0

module load julia
module load julia-mpi
julia --project=. script.jl
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=standard
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=128
#SBATCH --cpus-per-task=1
#SBATCH --mem-per-cpu=0

module use /appl/local/csc/modulefiles
module load julia
module load julia-mpi
julia --project=. script.jl

Yksi GPU

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
└── script.jl     # Julia script
Project.toml
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
script.jl
using CUDA

A = rand(2^9, 2^9)
A_d = CuArray(A)
B_d = A_d * A_d
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=gpumedium
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=72
#SBATCH --gres=gpu:gh200:1

module purge
module load julia
module load julia-cuda
julia --project=. script.jl
Project.toml
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"

[compat]
CUDA = "< 5.9"
script.jl
using CUDA

A = rand(2^9, 2^9)
A_d = CuArray(A)
B_d = A_d * A_d
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=gpusmall
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=32
#SBATCH --gres=gpu:a100:1

module load julia
module load julia-cuda
julia --project=. script.jl
Project.toml
[deps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
script.jl
using AMDGPU

A = rand(2^9, 2^9)
A_d = ROCArray(A)
B_d = A_d * A_d
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small-g
#SBATCH --time=00:15:00
#SBATCH --nodes=1
#SBATCH --gpus-per-node=1
#SBATCH --ntasks-per-node=1
#SBATCH --cpus-per-task=8
#SBATCH --mem-per-cpu=1750

module use /appl/local/csc/modulefiles
module load julia
module load julia-amdgpu
julia --project=. script.jl

GPU-aware MPI

Käytämme seuraavaa hakemistorakennetta ja oletamme, että se on työhakemistomme. prog.jl-koodi on mukautettu tästä lähteestä.

.
├── Project.toml  # Julia environment
├── batch.sh      # Slurm batch script
├── prog.jl       # Julia GPU-aware MPI program
└── script.jl     # Julia script
script.jl
using MPI
mpiexec(mpirun -> run(`$mpirun julia --project=. prog.jl`))
Project.toml
[deps]
CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba"
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
prog.jl
using MPI
using CUDA

const gpu_devices = CUDA.devices()
const num_devices = length(gpu_devices)

MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
# select device
comm_l = MPI.Comm_split_type(comm, MPI.COMM_TYPE_SHARED, rank)
rank_l = MPI.Comm_rank(comm_l)
device = CUDA.device!(mod(rank_l, num_devices))
gpu_id = CUDA.deviceid(CUDA.device())
# select device
size = MPI.Comm_size(comm)
dst  = mod(rank+1, size)
src  = mod(rank-1, size)
println("rank=$rank rank_loc=$rank_l (gpu_id=$gpu_id - $device), size=$size, dst=$dst, src=$src")
N = 2^16  # Minimum array size for gdrcopy to work.
send_mesg = CuArray{Float64}(undef, N)
recv_mesg = CuArray{Float64}(undef, N)
fill!(send_mesg, Float64(rank))
CUDA.synchronize()
rank==0 && println("start sending...")
MPI.Sendrecv!(send_mesg, dst, 0, recv_mesg, src, 0, comm)
println("sum(recv_mesg) on proc $rank: $(sum(recv_mesg))")
rank==0 && println("done.")
MPI.Finalize()
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=gpumedium
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --ntasks-per-node=4
#SBATCH --cpus-per-task=72
#SBATCH --gres=gpu:gh200:4

module purge
module load julia
module load julia-mpi
module load julia-cuda
julia --project=. script.jl
Project.toml
[deps]
AMDGPU = "21141c5a-9bdb-4563-92ae-f87d6854732e"
MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195"
prog.jl
using MPI
using AMDGPU
MPI.Init()
comm = MPI.COMM_WORLD
rank = MPI.Comm_rank(comm)
# select device
comm_l = MPI.Comm_split_type(comm, MPI.COMM_TYPE_SHARED, rank)
rank_l = MPI.Comm_rank(comm_l)
device = AMDGPU.device_id!(rank_l+1)
gpu_id = AMDGPU.device_id(AMDGPU.device())
# select device
size = MPI.Comm_size(comm)
dst  = mod(rank+1, size)
src  = mod(rank-1, size)
println("rank=$rank rank_loc=$rank_l (gpu_id=$gpu_id - $device), size=$size, dst=$dst, src=$src")
N = 4
send_mesg = ROCArray{Float64}(undef, N)
recv_mesg = ROCArray{Float64}(undef, N)
AMDGPU.synchronize()
rank==0 && println("start sending...")
MPI.Sendrecv!(send_mesg, dst, 0, recv_mesg, src, 0, comm)
println("recv_mesg on proc $rank: $recv_mesg")
rank==0 && println("done.")
batch.sh
#!/bin/bash
#SBATCH --account=<project>
#SBATCH --partition=small-g
#SBATCH --time=00:15:00
#SBATCH --nodes=2
#SBATCH --gpus-per-node=8
#SBATCH --ntasks-per-node=8
#SBATCH --cpus-per-task=8
#SBATCH --mem-per-cpu=0

module use /appl/local/csc/modulefiles
module load julia
module load julia-mpi
module load julia-amdgpu
julia --project=. script.jl

Huomioita

Monisäikeisyys lineaarialgebrassa

Julia käyttää OpenBLASia oletusarvoisena LinearAlgebra-taustajärjestelmänä. Ulkoiset lineaarialgebran taustajärjestelmät, kuten OpenBLAS, käyttävät sisäistä säikeistystä. Voimme asettaa niiden säiemäärät ympäristömuuttujilla. julia-moduuli asettaa ne CPU-säikeiden määrään.

export OPENBLAS_NUM_THREADS=$JULIA_CPU_THREADS

Meidän täytyy varoa ytimien ylivaraamista, kun käytämme BLAS-operaatioita Julia-säikeiden tai -prosessien sisällä. Voimme muuttaa BLAS-säikeiden määrää ajon aikana funktiolla BLAS.set_num_threads.

using LinearAlgebra

# Number of threads
n = Threads.nthreads()

# Define a matrix
X = rand(1000, 1000)

# Set the number of threads to one before performing BLAS operations of multiple Julia threads.
BLAS.set_num_threads(1)
Y = zeros(n)
Threads.@threads for i in 1:n  # uses n Julia threads
    Y[i] = sum(X * X)          # uses one BLAS thread
end

# Set the number of threads back to the default when performing BLAS operation on a single Julia Thread.
BLAS.set_num_threads(n)
Z = zeros(n)
for i in 1:n                   # uses one Julia thread
    Z[i] = sum(X * X)          # uses n BLAS threads
end

On olemassa huomioitavia rajoitteita, jos OpenBLASissa käytetään BLAS-säikeille jotain muuta määrää kuin yksi tai kaikki ytimet.

Suomenkielinen tekoälykäännös

Sisällössä voi esiintyä virheellistä tietoa tekoälykäännöksestä johtuen.

Klikkaa tästä antaaksesi palautetta