Многопоточность
Этот экспериментальный интерфейс поддерживает возможности многопоточности Julia. Типы и функции, описанные здесь, могут (и, вероятно, будут) изменяться в будущем.
Base.Threads.threadidФункция
Threads.threadid()
Получить идентификатор текущей потока выполнения. У главного потока ID 1.
Base.Threads.nthreadsФункция
Threads.nthreads()
Получить количество потоков, доступных для процесса Julia. Это верхняя граница включительно для threadid().
Base.Threads.@threadsМакрос
Threads.@threads
Макрос для распараллеливания цикла for для выполнения с несколькими потоками. Он порождает nthreads() количество потоков, распределяет пространство итераций между ними и выполняет итерации параллельно. В конце цикла устанавливается барьер, который ожидает завершения всех потоков, и цикл возвращается.
Base.Threads.AtomicТип
Threads.Atomic{T}
Содержит ссылку на объект типа T, гарантируя, что к нему обращаются атомарно, т.е. безопасно для нескольких потоков.
Только определенные «простые» типы могут использоваться атомарно, а именно примитивные булевы, целые и типы с плавающей точкой. Это Bool, Int8...Int128, UInt8...UInt128, и Float16...Float64.
Новые атомарные объекты могут быть созданы из значений, не являющихся атомарными; если ни один не указан, атомарный объект инициализируется нулём.
К атомарным объектам можно получить доступ, используя обозначение []:
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> x[] = 1
1
julia> x[]
1
Атомарные операции используют префикс atomic_, такие как atomic_add!, atomic_xchg! и т.д.
Base.Threads.atomic_cas!Функция
Threads.atomic_cas!(x::Atomic{T}, cmp::T, newval::T) where T
Атомарно сравнить и установить x
Атомарно сравнивает значение в x с cmp. Если они равны, запишите newval в x. В противном случае оставляет x без изменений. Возвращает старое значение в x. Сравнивая возвращенное значение с cmp (через ===) можно определить, было ли x изменено и теперь содержит новое значение newval.
Дополнительные сведения см. в инструкции LLVM cmpxchg.
Эта функция может использоваться для реализации транзакционных семантик. Перед транзакцией записывается значение в x. После транзакции новое значение сохраняется только в том случае, если x не был изменён.
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_cas!(x, 4, 2);
julia> x
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_cas!(x, 3, 2);
julia> x
Base.Threads.Atomic{Int64}(2)
исходный код
Base.Threads.atomic_xchg!Функция
Threads.atomic_xchg!(x::Atomic{T}, newval::T) where T
Атомарно обменивает значение в x
Атомарно меняет значение в x на newval. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw xchg.
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_xchg!(x, 2)
3
julia> x[]
2
исходный код
Base.Threads.atomic_add!Функция
Threads.atomic_add!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
Атомарно добавить val к x
Выполняет x[] += val атомарно. Возвращает старое значение. Не определено для Atomic{Bool}.
Дополнительные сведения см. в инструкции LLVM atomicrmw add.
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_add!(x, 2)
3
julia> x[]
5
исходный код
Base.Threads.atomic_sub!Функция
Threads.atomic_sub!(x::Atomic{T}, val::T) where T <: ArithmeticTypes
Атомарно вычесть val из x
Выполняет x[] -= val атомарно. Возвращает старое значение. Не определено для Atomic{Bool}.
Дополнительные сведения см. в инструкции LLVM atomicrmw sub.
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_sub!(x, 2)
3
julia> x[]
1
исходный код
Base.Threads.atomic_and!Функция
Threads.atomic_and!(x::Atomic{T}, val::T) where T
Атомарно побитовое И x с val
Выполняет x[] &= val атомарно. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw and.
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_and!(x, 2)
3
julia> x[]
2
исходный код
Base.Threads.atomic_nand!Функция
Threads.atomic_nand!(x::Atomic{T}, val::T) where T
Атомарно побитовое НЕ-И (not-and) x с val
Выполняет x[] = ~(x[] & val) атомарно. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw nand.
Примеры
julia> x = Threads.Atomic{Int}(3)
Base.Threads.Atomic{Int64}(3)
julia> Threads.atomic_nand!(x, 2)
3
julia> x[]
-3
исходный код
Base.Threads.atomic_or!Функция
Threads.atomic_or!(x::Atomic{T}, val::T) where T
Атомарно побитовое ИЛИ x с val
Выполняет x[] |= val атомарно. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw or.
Примеры
julia> x = Threads.Atomic{Int}(5)
Base.Threads.Atomic{Int64}(5)
julia> Threads.atomic_or!(x, 7)
5
julia> x[]
7
исходный код
Base.Threads.atomic_xor!Функция
Threads.atomic_xor!(x::Atomic{T}, val::T) where T
Атомарно побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ (exclusive-or) x с val
Выполняет x[] $= val атомарно. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw xor.
Примеры
julia> x = Threads.Atomic{Int}(5)
Base.Threads.Atomic{Int64}(5)
julia> Threads.atomic_xor!(x, 7)
5
julia> x[]
2
исходный код
Base.Threads.atomic_max!Функция
Threads.atomic_max!(x::Atomic{T}, val::T) where T
Атомарно сохранить максимальное значение из x и val в x
Выполняет x[] = max(x[], val) атомарно. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw max.
Примеры
julia> x = Threads.Atomic{Int}(5)
Base.Threads.Atomic{Int64}(5)
julia> Threads.atomic_max!(x, 7)
5
julia> x[]
7
исходный код
Base.Threads.atomic_min!Функция
Threads.atomic_min!(x::Atomic{T}, val::T) where T
Атомарно сохранить минимальное значение из x и val в x
Выполняет x[] = min(x[], val) атомарно. Возвращает старое значение.
Дополнительные сведения см. в инструкции LLVM atomicrmw min.
Примеры
julia> x = Threads.Atomic{Int}(7)
Base.Threads.Atomic{Int64}(7)
julia> Threads.atomic_min!(x, 5)
7
julia> x[]
5
исходный код
Base.Threads.atomic_fenceФункция
Threads.atomic_fence()
Вставка барьера последовательной согласованности памяти
Вставляет барьер памяти с семантикой последовательной согласованности. Существуют алгоритмы, где это необходимо, т.е. где порядок приобретения/освобождения недостаточен.
Вероятно, это очень дорогостоящая операция. Поскольку все другие атомарные операции в Julia уже имеют семантику приобретения/освобождения, явные барьеры в большинстве случаев не нужны.
Дополнительные сведения см. в инструкции LLVM fence.
ccall с использованием пула потоков (Экспериментально)
Base.@threadcallМакрос
@threadcall((cfunc, clib), rettype, (argtypes...), argvals...)
Макрос @threadcall вызывается так же, как ccall, но выполняет работу в другом потоке. Это полезно, когда вы хотите вызвать блокирующую C-функцию, не заставляя основной julia поток блокироваться. Конкурентность ограничена размером пула потоков libuv, который по умолчанию равен 4 потокам, но может быть увеличен путем установки переменной среды UV_THREADPOOL_SIZE и перезапуска процесса julia.
Обратите внимание, что вызываемая функция не должна обращаться обратно в Julia.
исходный кодПримитивы синхронизации
Base.Threads.AbstractLockТип
AbstractLock
Абстрактный супертип, описывающий типы, реализующие потокобезопасные синхронизационные примитивы: lock, trylock, unlock и islocked.
Base.lockФункция
lock(lock)
Получить lock, когда он станет доступным. Если блокировка уже захвачена другой задачей/потоком, дождаться её освобождения.
Каждая lock должна быть согласована с unlock.
Base.unlockФункция
unlock(lock)
Освобождает владение lock.
Если это рекурсивная блокировка, которая была захвачена ранее, декрементирует внутренний счётчик и возвращает немедленно.
исходный код
Base.trylockФункция
trylock(lock) -> Success (Boolean)
Захватить блокировку, если она доступна, и вернуть true, если операция успешна. Если блокировка уже захвачена другой задачей/потоком, вернуть false.
Каждая успешная trylock должна быть согласована с unlock.
Base.islockedФункция
islocked(lock) -> Status (Boolean)
Проверить, удерживается ли lock какой-либо задачей/потоком. Не следует использовать для синхронизации (используйте вместо этого trylock).
Base.ReentrantLockТип
ReentrantLock()
Создаёт рекурсивную блокировку для синхронизации Taskов. Одна и та же задача может захватывать блокировку любое количество раз. Каждая lock должна быть согласована с unlock.
Эта блокировка НЕ потокобезопасна. См. Threads.Mutex для потокобезопасной блокировки.
Base.Threads.MutexТип
Mutex()
Стандартные системные мьютексы для блокировки критических участков кода.
В Windows — это объект критической секции, в pthreads — это pthread_mutex_t.
См. также SpinLock для более лёгкой блокировки.
Base.Threads.SpinLockТип
SpinLock()
Создаёт нерекурсивную блокировку. Рекурсивное использование приведёт к тупику. Каждая lock должна быть согласована с unlock.
Спин-блокировки типа «проверь-и-проверь-и-установи» самые быстрые при до 30-ти конкурирующих потоков. Если у вас больше контенции, возможно, блокировка — не лучший способ синхронизации.
См. также RecursiveSpinLock для версии, допускающей рекурсию.
См. также Mutex для более эффективной версии на одном ядре или если блокировка может удерживаться значительное время.
Base.Threads.RecursiveSpinLockТип
RecursiveSpinLock()
Создаёт рекурсивную блокировку. Один и тот же поток может захватывать блокировку любое количество раз. Каждая lock должна быть согласована с unlock.
См. также SpinLock для немного более быстрой версии.
См. также Mutex для более эффективной версии на одном ядре или если блокировка может удерживаться значительное время.
Base.SemaphoreТип
Semaphore(sem_size)
Создаёт счётный семафор, который позволяет максимум sem_size приобретений быть активными одновременно. Каждое приобретение должно быть согласовано с освобождением.
Этот конструкт НЕ потокобезопасен.
исходный код
Base.acquireФункция
acquire(s::Semaphore)
Дождаться, пока один из sem_size разрешений станет доступным, блокируясь, пока одно не будет приобретено.
Base.releaseФункция
release(s::Semaphore)
Возвратить одно разрешение в пул, возможно, позволив другой задаче его получить и возобновить выполнение.
исходный код
© 2009–2019 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v0.7.0/base/multi-threading/