Spec-Zone.ru › Julia 1.0

Многопоточность

Этот экспериментальный интерфейс поддерживает возможности многопоточности Julia. Типы и функции, описанные здесь, могут (и, вероятно, будут) изменяться в будущем.

Base.Threads.threadidФункция

Threads.threadid()

Получить идентификатор текущей потоковой нити выполнения. У главного потока идентификатор 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

Атомарно выполняет побитовую операцию AND 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

Атомарно выполняет побитовую операцию NAND (не-и) 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

Атомарно выполняет побитовую операцию OR 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

Атомарно выполняет побитовую операцию XOR (исключающее ИЛИ) 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/v1.0.4/base/multi-threading/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API