Многопоточность
Этот экспериментальный интерфейс поддерживает многопоточные возможности Julia. Типы и функции, описанные здесь, могут (и, скорее всего, будут) изменены в будущем.
Base.Threads.threadidФункция
Threads.threadid()
Получить идентификатор текущего потока выполнения. У главного потока ID 1.
Base.Threads.nthreadsФункция
Threads.nthreads()
Получить количество потоков, доступных для процесса Julia. Это верхняя граница (включающая значение) для threadid().
Base.Threads.@threadsМакрос
Threads.@threads
Макрос для распараллеливания цикла for для работы с несколькими потоками. Он создаёт nthreads() потоков, распределяет пространство итераций между ними и выполняет итерации параллельно. В конце цикла устанавливается барьер, который ожидает завершения работы всех потоков, и цикл возвращает результат.
Base.Threads.@spawnМакрос
Threads.@spawn expr
Создать и запустить Task в любом доступном потоке. Чтобы дождаться завершения задачи, вызовите wait на результате этого макроса или вызовите fetch, чтобы подождать и получить возвращаемое значение.
Эта функция в настоящее время считается экспериментальной.
Этот макрос доступен начиная с Julia 1.3.
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
Атомарное побитовое НЕ-И 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
Атомарное побитовое ИСКЛЮЧАЮЩЕЕ ИЛИ 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.SpinLockТип
SpinLock()
Создает нерекурсивную блокировку. Рекурсивное использование приведет к тупику. Каждый lock должен быть сопоставлен с unlock.
Блокировки типа «проба-проба-установка» являются самыми быстрыми для примерно до 30 конкурирующих потоков. Если у вас больше конкуренции, то, возможно, блокировка — не лучший способ синхронизации.
исходный код
© 2009–2020 Jeff Bezanson, Stefan Karpinski, Viral B. Shah, and other contributors
Licensed under the MIT License.
https://docs.julialang.org/en/v1.3.1/base/multi-threading/