Slide 1

Slide 1 text

S_Shimotori SynchronizationΛࢧ͑Δٕज़ Θ͍Θ͍swiftc #42 ΦϑϥΠϯ @ ϝϧΧϦ

Slide 2

Slide 2 text

S_Shimotori • X: S_Shimotori_pub • Speaker Deck: s_shimotori

Slide 3

Slide 3 text

ຊ೔ͷϞνϕʔγϣϯͷ࿩

Slide 4

Slide 4 text

ฒߦϓϩάϥϛϯάೖ໳ • ΦϥΠϦʔ • Swift͸શ͘ग़ͯ͜ͳ͍ 4 https://www.oreilly.co.jp//books/9784873119595/

Slide 5

Slide 5 text

ग़ൃ఺ • C/RustͰॻ͔Ε͍ͯΔαϯϓϧίʔυΛpure SwiftͰॻ͘ʂ 5

Slide 6

Slide 6 text

࢖͑ͦ͏ͳ΍ͭ • Swift Atomics (apple/swift-atomics) • Synchronization (swiftlang/swift/blob/main/stdlib/public/Synchronization/) • Grand Central Dispatch (apple/swift-corelibs-libdispatch) 6

Slide 7

Slide 7 text

Swift Atomics ⚛︎ ︎ • ༁ɿຊύοέʔδ͸Swift༻ͷatomicsϥΠϒϥϦΛ࣮૷͢Δɻ੔਺΍ϙΠϯλ ΛؚΉ༷ʑͳSwiftͷܕʹෆՄ෼ૢ࡞Λఏڙ͢Δɻ໨త͸ɺ༐׶ͳ։ൃऀ͕ SwiftͰ௚઀ʹಉظߏ଄ΛߏஙͰ͖ΔΑ͏ʹ͢Δ͜ͱͰ͋Δɻ • ࠷৽όʔδϣϯͷϦϦʔε͕2023೥10݄ɺ࠷৽ίϛοτ͕2024೥7݄ • ManagedAtomicsͱUnsafeAtomics͘Β͍͔͠ͳ͍ 7 https://github.com/apple/swift-atomics

Slide 8

Slide 8 text

Synchronization framework • ༁ɿ௿ਫ४ͷϓϦϛςΟϒͳૢ࡞Λ༻͍ͯಉظߏ଄Λߏங͢Δɻ • iOS 18.0+ɺmacOS 15.0+ • AtomicͱMutex͕͋Δ • SE-0410: Low-Level Atomic Operations (Swift 6.0) • swift-atomicsΛେ͍ʹࢀߟʹͯ͠࡞ͬͨΈ͍ͨ • SE-0433: Synchronous Mutual Exclusion Lock (Swift 6.0) 8 https://developer.apple.com/documentation/synchronization

Slide 9

Slide 9 text

SynchronizationͷAtomicΛ ࢖ͬͯΈΔʂ

Slide 10

Slide 10 text

10 • Α͘ͳ͍ͷͰɺconcurrency checkΛ༗ޮʹ͢ΔͱΤϥʔʹͳΔ Α͘ͳ͍ιʔείʔυͷྫ var counter = 0 DispatchQueue.concurrentPerform(iterations: 10) { _ in for _ in 0 ..< 1_000_000 { counter += 1 } } print(counter) Mutation of captured var ‘counter’ in concurrently-executing code 👈Swift 5Ͱ࣮ߦ͢Δͱ10_000_000ʹͳΒͳ͍

Slide 11

Slide 11 text

11 • Atomicʹੜ͍͑ͯΔϝιουΛ࢖ͬͯ஋ΛಡΈॻ͖͢Δ SynchronizationͷAtomicͷ࢖༻ྫ let counter = Atomic(0) DispatchQueue.concurrentPerform(iterations: 10) { _ in for _ in 0 ..< 1_000_000 { counter.wrappingAdd(1, ordering: .relaxed) } } print(counter.load(ordering: .relaxed)) 👈10_000_000ʹͳΔʂ https://github.com/swiftlang/swift-evolution/blob/.../proposals/0410-atomics.md#proposed-solution

Slide 12

Slide 12 text

12 • Atomicʹੜ͍͑ͯΔϝιουΛ࢖ͬͯ஋ΛಡΈॻ͖͢Δ SynchronizationͷAtomicͷ࢖༻ྫ let counter = Atomic(0) DispatchQueue.concurrentPerform(iterations: 10) { _ in for _ in 0 ..< 1_000_000 { counter.wrappingAdd(1, ordering: .relaxed) } } print(counter.load(ordering: .relaxed)) https://github.com/swiftlang/swift-evolution/blob/.../proposals/0410-atomics.md#proposed-solution

Slide 13

Slide 13 text

Atomicʹੜ͑ͯΔϝιουͨͪ • addɺsubtractɿΦʔόʔϑϩʔͪ͠Ό͏ • wrapping(Add|Subtract)ɿϥοϓΞϥ΢ϯυͯ͘͠ΕΔ • bitwise(And|Or|Xor)ɿIntಉ࢜ • logical(And|Or|Xor)ɿBoolಉ࢜ • maxɺminɿͦͷ·Μ· • compareExchangeɿڧ͍൛ • weakCompareExchangeɿऑ͍൛ʢspurious failureΛڐ༰͢Δʣ • exchange(_ desired: consuming Value, ordering: AtomicUpdateOrdering) -> Valueɿcompare͠ͳ͍ • load(ordering: AtomicLoadOrdering) -> ValueɿಡΉ • store(_ desired: consuming Value, ordering: AtomicStoreOrdering)ɿॻ͘ 13 ※த਎ʹΑͬͯ࢖͑Δϝιου͸ҟͳΓ·͢

Slide 14

Slide 14 text

Mutex΋ͪΐͬͱ঺հʂ

Slide 15

Slide 15 text

Mutex • DarwinͰ͸ϩοΫʹos_unfair_lockΛ࢖༻ • Linux΍Windows΍WebAssembly༻ͷ࣮૷΋͋Δʢࡉ͔͍ڍಈ͸ҟͳΔʣ • os.OSAllocatedUnfairLockͱͷҧ͍ • Mutexʹ͸~Copyableͳ΋ͷ͔͠౉ͤͳ͍ 15 https://github.com/swiftlang/swift-evolution/blob/.../proposals/0433-mutex.md
 https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Mutex/Mutex.swift
 https://developer.apple.com/documentation/os/osallocatedunfairlock

Slide 16

Slide 16 text

SynchronizationΛࢧ͑Δٕज़ ٕज़ͱ͍͏͔ཧ࿦ͱ͍͏͔จ๏ͱ͍͏͔……

Slide 17

Slide 17 text

ࠓ೔ͷ࿩୊ • 🦌ʮInt͔͠౉ͤͳ͍ΑͶʯ • ͳΜ͔ݫ͘͠ͳ͍ʁ • ΦʔμϦϯάͬͯͳʹ 17

Slide 18

Slide 18 text

ࠓ೔ͷ࿩୊ • 🦌ʮInt͔͠౉ͤͳ͍ΑͶʯ • ͳΜ͔ݫ͘͠ͳ͍ʁ • ΦʔμϦϯάͬͯͳʹ 18

Slide 19

Slide 19 text

struct Atomic • AtomicRepresentable • static func decodeAtomicRepresentation( consuming Self.AtomicRepresentation ) -> Self • static func encodeAtomicRepresentation( consuming Self ) -> Self.AtomicRepresentation 19 https://developer.apple.com/documentation/synchronization/atomicrepresentable

Slide 20

Slide 20 text

ඪ४ͰAtomicRepresentableͳօ͞Μ • ಛʹग़൪͕͋Γͦ͏ͳ΋ͷΛಠஅͰൈਮ • Intͷօ͞Μ • UIntͷօ͞Μ • ුಈখ਺఺਺ͷօ͞Μ • Bool • ϙΠϯλͷօ͞Μ 20

Slide 21

Slide 21 text

ඪ४ͰAtomicRepresentationͳօ͞Μ • UIntͷօ͞Μ • Intͷօ͞Μ • struct WordPair • double wide atomicsରԠͷ؀ڥԼͰ2ͭͷUIntΛ·ͱΊͯѻ͏ 21 https://developer.apple.com/documentation/synchronization/wordpair
 https://github.com/swiftlang/swift/blob/.../lib/Basic/LangOptions.cpp#L313-L409 Ҏ্ʂ

Slide 22

Slide 22 text

AtomicIntegers.swift.gyb Ұ෦ൈਮ͓ͯ͠ૹΓ͓ͯ͠Γ·͢ • LLVMͷΞτϛοΫ໋ྩΛ͏·͘ϥοϓͯ͠Δ͚ͩ 22 public func ${lowerFirst(name)}( _ operand: ${intType}, ordering: AtomicUpdateOrdering ) -> (oldValue: ${intType}, newValue: ${intType}) { Builtin.atomicrmw_${atomicOperationName(intType, builtinName)}_${llvmOrder}_Int64( _rawAddress, operand._value ) } https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Atomics/AtomicIntegers.swift.gyb#L95-L157
 https://github.com/swiftlang/swift/blob/.../utils/SwiftAtomics.py#L71-L82
 https://llvm.org/docs/LangRef.html#atomicrmw-instruction

Slide 23

Slide 23 text

public func ${lowerFirst(name)}( _ operand: ${intType}, ordering: AtomicUpdateOrdering ) -> (oldValue: ${intType}, newValue: ${intType}) { Builtin.atomicrmw_${atomicOperationName(intType, builtinName)}_${llvmOrder}_Int64( _rawAddress, operand._value ) } AtomicIntegers.swift.gyb Ұ෦ൈਮ͓ͯ͠ૹΓ͓ͯ͠Γ·͢ • LLVMͷΞτϛοΫ໋ྩΛ͏·͘ϥοϓͯ͠Δ͚ͩ 23 integerOperations = [ # Swift name, llvm name, operator, doc name ("WrappingAdd", "add", "&+", "wrapping add"), ("WrappingSubtract", "sub", "&-", "wrapping subtract"), … https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Atomics/AtomicIntegers.swift.gyb#L95-L157
 https://github.com/swiftlang/swift/blob/.../utils/SwiftAtomics.py#L71-L82
 https://llvm.org/docs/LangRef.html#atomicrmw-instruction

Slide 24

Slide 24 text

IntҎ֎΋Atomicʹ౉͍ͨ͠ʂ • σʔλͷ௕͕͞64bitҎ಺ʹऩ·ΔͳΒ࣮࣭Int64ͳͷͰηʔϑ • UnsafePointer΋IntͬͯݴͬͯΔ • WordPairͳΒUIntΛಉ࣌ʹ2ͭ΋ѻ͓͑ͯಘ • ྫɿIntܕϓϩύςΟ͕2ͭ͋Δߏ଄ମΛAtomicRepresentableʹ͢Δ 24 https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Atomics/AtomicPointers.swift#L40-L42 Int.encodeAtomicRepresentation( Int(bitPattern: value) )

Slide 25

Slide 25 text

ࠓ೔ͷ࿩୊ • 🦌ʮInt͔͠౉ͤͳ͍ΑͶʯ • ͳΜ͔ݫ͘͠ͳ͍ʁ • ΦʔμϦϯάͬͯͳʹ 25

Slide 26

Slide 26 text

ͳΜ͔ݫ͍͠ϙΠϯτ3ͭ • ~CopyableͰ͋Δ • letଋറͰએݴ͠ͳ͚Ε͹ͳΒͳ͍ • Ҿ਺ʹ౉͢ΦʔμϦϯά͸ίϯύΠϧ࣌ఆ਺Ͱͳ͚Ε͹ͳΒͳ͍ 26

Slide 27

Slide 27 text

27 • swift-atomicsͱҟͳΓ~Copyable͕͍͍ͭͯΔ ݫ͍͠ᶃɿSynchronizationͰ͸~Copyable // Synchronization struct Atomic: ~Copyable struct Mutex: ~Copyable // swift-atomics class ManagedAtomic

Slide 28

Slide 28 text

ݫ͍͠ᶄɿletଋറͰએݴ͠ͳ͚Ε͹ͳΒͳ͍ • Atomic΋Mutex΋varͰએݴͰ͖ͳ͍ • swift-atomicsͷAtomicͳΒvar͕ڐ͞Εͨ 28 https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Atomics/Atomic.swift#L16-L20
 https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Mutex/Mutex.swift#L34-L37 @available(SwiftStdlib 6.0, *) @frozen @_rawLayout(like: Value.AtomicRepresentation) @_staticExclusiveOnly public struct Atomic: ~Copyable 👈͍ͭ͜ͷ͍ͤʂ

Slide 29

Slide 29 text

@_staticExclusiveOnly • -enable-experimental-feature͕ඞཁ • ~Copyableͳܕʹ͔͚ͭ͠ΒΕͳ͍ • Atomic͕~Copyableͳͷ͸͜ΕͷͨΊ…ͳͷ͔ͳ͋…ʁ • NGߦҝɿίϐʔɺvarɺinout 29 https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/CMakeLists.txt#L75
 https://github.com/swiftlang/swift/blob/.../test/attr/attr_static_exclusive_only.swift#L3

Slide 30

Slide 30 text

@_staticExclusiveOnlyʹΑΔ֬ೝ • varΛ࢖ͬͯͳ͍͔ͷ֬ೝ • void visitBoundVariable(VarDecl *VD)ͷ్த • inoutͰ౉͞Εͯͳ͍͔ͷ֬ೝ • TypeResolver::resolveASTFunctionTypeParams(...)ͷ్த 30 https://github.com/swiftlang/swift/blob/.../lib/Sema/TypeCheckType.cpp#L3853-L3860
 https://github.com/swiftlang/swift/blob/.../lib/Sema/TypeCheckDeclPrimary.cpp#L2672-L2695 SD->getAttrs().hasAttribute()

Slide 31

Slide 31 text

@_rawLayout(like: Value.AtomicRepresentation) • ݴޠʹΑΔ؅ཧΛʢ΄΅ʣ͠ͳ͍raw storageΛ࣋ͭ • ΞτϛοΫͳͲͷಛघͳΞΫηεΛߦ͏σʔλߏ଄ͷετϨʔδ • ~Copyableͳܕʹ͔͚ͭ͠ΒΕͣɺstored propertyΛ࣋ͭ͜ͱ͕Ͱ͖ͳ͘ͳΔ • ϥΠϑλΠϜશମʹΘͨΓ҆ఆͨ͠ΞυϨεΛ࣋ͭ • ܕͷαΠζͱΞϥΠϯϝϯτ͸like: Tͱಉ͡ 31 https://github.com/swiftlang/swift/blob/.../docs/ReferenceGuides/UnderscoredAttributes.md#_rawlayout
 https://github.com/swiftlang/swift/blob/.../test/Sema/raw_layout.swift

Slide 32

Slide 32 text

൫ੴͳ෍ਞʂ • ~Copyableɺ@_staticExclusiveOnlyɺ@_rawLayout͕ἧͬͯڧͦ͏ 32 let counter = Atomic(0) 👆ͨͩ1ͭͷॴ༗ݖ ಛఆͷAtomicΦϒδΣΫτ͚ͩΛࢦ͢👆 @_staticExclusiveOnly ~Copyable 👆ΞυϨε͕҆ఆ

Slide 33

Slide 33 text

the Law of Exclusivity • ม਺ͷมߋͱม਺ΞΫηε͸ഉଞతͰͳ͚Ε͹ͳΒͳ͍ • ੩త਍அ΍ಈత਍அΛͯ͠ҧ൓͕ͳ͍͔؂ࢹ͍ͯ͠Δ • letଋറͳͲͷෆมͷϝϞϦ͸ॻ͖ࠐΈ͕ൃੜͤͣಈతͳνΣοΫ͕ෆཁ • letͳΒ࣮ߦ࣌ʹΦʔόʔϔου͕ൃੜ͠ͳ͍ʂ 33 https://www.swift.org/blog/swift-5-exclusivity/
 https://github.com/swiftlang/swift-evolution/blob/.../proposals/0176-enforce-exclusive-access-to-memory.md

Slide 34

Slide 34 text

ݫ͍͠ᶅɿΦʔμϦϯά͸ίϯύΠϧఆ਺Ͱʂ • ΦʔμϦϯάʢޙड़ʣΛࢦఆͰ͖Δ͕ɺఆ਺Ͱࢦఆ͠ͳ͍ͱΤϥʔʹͳΔ • swift-atomics΋ಉ༷ɹͭ·Γ👇͸݁ߏલ͔Β͋Δ • @_semantics("atomics.requires_constant_orderings")Ͱ࣮ݱ 34 var ordering = AtomicUpdateOrdering.relaxed atomic.add(1, ordering: ordering) Ordering argument must be a static method or property of ‘… 👆ઐ༻ͷΤϥʔϝοηʔδ͕͋Δ https://github.com/swiftlang/swift/blob/.../stdlib/public/Synchronization/Atomics/AtomicIntegers.swift.gyb#L110
 https://github.com/apple/swift-atomics/blob/.../Sources/Atomics/Types/ManagedAtomic.swift#L58
 https://github.com/swiftlang/swift/blob/.../test/Sema/diag_constantness_check.swift
 https://github.com/swiftlang/swift/blob/.../include/swift/AST/DiagnosticsSema.def#L7470-L7472

Slide 35

Slide 35 text

@_semantics("...") • SwiftΦϓςΟϚΠβͰΑ͘࢖ΘΕͯΔΒ͍͠ • ௚༁ɿߴਫ४ͳ࠷దԽʢߴਫ४ݴޠͰ͸Ұൠతʣͱ௿ਫ४ͷ࠷దԽͷ྆ํ Λ࣮ݱ͢ΔͨΊɺ ඪ४ϥΠϒϥϦͷҰ෦ʹΞϊςʔγϣϯΛ͚ͭɺ Swiftඪ ४ϥΠϒϥϦͷσʔλܕʹ͓͚ΔυϝΠϯݻ༗ͷߴਫ४ͳૢ࡞ͷηϚϯ ςΟΫεΛهड़͢Δɻ • ΦϓςΟϚΠβ͸λάʹԠͨ͡ॲཧΛߦ͏ • Array΍String΍DictionaryͳͲͰ΋࢖ΘΕ͍ͯΔ 35 https://github.com/swiftlang/swift/blob/.../include/swift/AST/SemanticAttrs.def#L92
 https://github.com/swiftlang/swift/blob/.../docs/HighLevelSILOptimizations.rst

Slide 36

Slide 36 text

HighLevelSILOptimizations.rstʹॻ͍ͯ͋ͬͨ͜ͱ • ࠷దԽͷύΠϓϥΠϯ 1. ·ͣhigh-levelͳ࠷దԽΛ͠·͢ 2. ͜͜ͰॳΊͯ@_semanticsͷ͍ͭͨؔ਺ΛΠϯϥΠϯԽ͠·͢ • ઌʹΠϯϥΠϯԽ͢ΔͱpassϞδϡʔϧ͕ͨͪ1. ͰࠔͬͪΌ͏͔Β 3. ΠϯϥΠϯԽޙʹlow-levelͳ࠷దԽΛ͠·͢ 36 https://github.com/swiftlang/swift/blob/.../docs/HighLevelSILOptimizations.rst ⚠Atomicͱ͸ؔ܎ͳ͍Έ͍ͨ⚠

Slide 37

Slide 37 text

݁ہ͍ͭΦʔμϦϯάҾ਺ΛνΣοΫͯ͠Δͷ͔ • static Expr *checkConstantness(Expr *expr)ͷத • ḷ͍ͬͯ͘ͱTypeCheckConstraints.cppʹḷΓண͘ʢ͋Εʁʣ • Sema checkͱͯ͠΍ͬͯΔ 37 https://github.com/swiftlang/swift/blob/.../lib/Sema/ConstantnessSemaDiagnostics.cpp#L334
 ↑
 https://github.com/swiftlang/swift/blob/.../lib/Sema/MiscDiagnostics.cpp#L6233
 ↑
 https://github.com/swiftlang/swift/blob/.../lib/Sema/TypeCheckConstraints.cpp#L338-L342 hasSemanticsAttr(funcDecl, semantics::ATOMICS_REQUIRES_CONSTANT_ORDERINGS)

Slide 38

Slide 38 text

SILͰ͸ͳ͘Sema checkΛબΜͩཧ༝ • ߏจ্ͷ੍ݶΛઃ͚Δ͜ͱʹΑΓɺղੳର৅ͷίʔυͷൣғ͕ݶఆ͞ΕΔ • ਖ਼نԽ΍৘ใଛࣦ͕͋ͬͨ͋ͱͩͱࠜຊతͳݪҼͷ਍அ͕೉͘͠ͳΔ 38 https://github.com/swiftlang/swift/pull/26969#issuecomment-610687501

Slide 39

Slide 39 text

ͳΜ͔ݫ͘͠ͳ͍ʁͷཧ༝ • ద੾ͳΞτϛοΫૢ࡞Λڧ͍ΔͨΊʹ੍໿Λઃ͚͍ͯΔ • ࣮ݱͷͨΊʹSynchronizationઐ༻ʢଟ෼ʣͷॲཧ͕࣮૷͞ΕͯΔ 39

Slide 40

Slide 40 text

ࠓ೔ͷ࿩୊ • 🦌ʮͳΜͰInt͔͠౉ͤͳ͍ͷʯ • ͳΜ͔ݫ͘͠ͳ͍ʁ • ΦʔμϦϯάͬͯͳʹ 40

Slide 41

Slide 41 text

Α͘Θ͔Βͳ͍ͷͰɺઆ໌ͷͨΊʹྫ୊Λग़͠·͢ • ྫ୊ʮlock-free, single-consumer stackʯͷ঺հ • Atomicͷ͓͔͛Ͱ͏·͍͘͘έʔε • ߟ͑ͳ͠ʹAtomicΛ࢖ͬͯ͏·͍͔͘ͳ͍έʔε • ΦʔμϦϯάΛಋೖͯ͠ղܾʂ • ͳΜͰݫ͍͠ͷ 41

Slide 42

Slide 42 text

lock-free, single-consumer stackΛ࡞Δ • ಺෦తʹ͸linked listͷߏ଄ • UnsafeMutablePointerͰͭͳ͕ͬͯΔ • push()͢Δͱϊʔυ͕૿͑ͯpop()͢Δͱϊʔυ͕ݮΔ • ෳ਺εϨου͔ΒͲΜͲΜpush()ͯ͠Α͍ • pop()ͷ࠷தʹผεϨου͔Βpop()͢Δͷ͸NGʢsingle-consumerʣ 42 ɿUnsafeMutablePointer Stack Node Node Node Node

Slide 43

Slide 43 text

Atomicͷ࢖͍Ͳ͜Ζ2Օॴ • ελοΫ͔Βϊʔυ΁ͷUnsafeMutablePointer • pop()࡞ۀதͷconsumerͷ਺ 43 Stack Node Node Node Node Atomic?> pop()தͷ
 consumer͕
 Nਓ Atomic

Slide 44

Slide 44 text

private let _consumerCount = Atomic(0) • pop()๯಄Ͱ+1ɺdeferͰ-1 • ๯಄Ͱ+1͢Δ͍ͭͰʹɺpreconditionͰ஋͕0Ͱ͋Δ͜ͱΛ͔֬ΊΔ 44 ଞͷਓ͕pop()ͯ͠ͳ͍ t εϨουA ࠓͷ஋Λ
 ಡΉ औಘͨ͠஋ʹ
 +1ͨ͠஋Λ
 ॻ͘ ࠓͷ஋Λ
 ಡΉ औಘͨ͠஋ʹ
 -1ͨ͠஋Λ
 ॻ͘ popͷ࡞ۀத… +1 -1

Slide 45

Slide 45 text

private let _consumerCount = Atomic(0) • pop()๯಄Ͱ+1ɺdeferͰ-1 • ๯಄Ͱ+1͢Δ͍ͭͰʹɺpreconditionͰ஋͕0Ͱ͋Δ͜ͱΛ͔֬ΊΔ 45 ଞͷਓ͕pop()ͯ͠ͳ͍ t εϨουA ࠓͷ஋Λ
 ಡΉ औಘͨ͠஋ʹ
 +1ͨ͠஋Λ
 ॻ͘ ࠓͷ஋Λ
 ಡΉ औಘͨ͠஋ʹ
 -1ͨ͠஋Λ
 ॻ͘ t Count 0 0 1

Slide 46

Slide 46 text

46 • _consumerCount͕0Ͱ͸ͳ͍ͷͰpreconditionͰΤϥʔʹͳΔ👍 multi-consumerʹͳͬͪΌ͏ͷΛ્ࢭ͢Δ t t Count εϨουA εϨουB 0 0 1 1 🚨💥 t

Slide 47

Slide 47 text

͔͜͜Β͕ຊ୊ʂ

Slide 48

Slide 48 text

48 • εϨουA͕·ͩ࡞ۀதͳͷʹεϨουB͕popΛࢼΈΔέʔε Atomic?>΋ѻ͏ͧʂ Count NodePtr εϨουA εϨουB ϊʔυૢ࡞ͯ͠ Χ΢ϯτ0ʹ͢Δ Χ΢ϯτ1ʹͯ͠ ϊʔυૢ࡞͢Δ 🚨💥

Slide 49

Slide 49 text

49 • ͋ͬɺઌʹ_consumerCountΛ0ʹ໭ͪ͠Όͬͨ😆 Atomic?>΋ѻ͏ͧʂ Count NodePtr εϨουA εϨουB 1 0

Slide 50

Slide 50 text

50 • ࡞ۀதͷConsumer͕͍ͳ͍Α͏ͳͷͰεϨουB͸ϊʔυΛૢ࡞͢Δ Atomic?>΋ѻ͏ͧʂ Count NodePtr εϨουA εϨουB 1 0 1

Slide 51

Slide 51 text

51 • _consumerCountͱprecondition͕ࢭΊͯ͘Εͳ͔ͬͨ😭😭😭 Atomic?>΋ѻ͏ͧʂ Count NodePtr ϊʔυͷϙΠϯλ͕ΊͪΌͪ͘Ό👆 εϨουA εϨουB

Slide 52

Slide 52 text

52 • ݪҼɿΧ΢ϯλૢ࡞ͱϊʔυૢ࡞ͷॱং͕ೖΕସΘ͔ͬͨΒ Atomic?>΋ѻ͏ͧʂ Count NodePtr εϨουA εϨουB 👈🚨

Slide 53

Slide 53 text

զʑʹඞཁͳ΋ͷ • happens before ʢ ʣͷॱ൪Λकͬͯ΋Β͏ͨΊͷ࢓૊Έ • ʮΠϕϯτ ͸Πϕϯτ ͷલʹى͜Δʢى͜Βͳ͚Ε͹ͳΒͳ͍ʣʯ • ൒ॱংؔ܎ • Atomic*Orderingͱ͍͏ΦϓγϣϯͰࢦఆՄೳ a b a → b a b 53

Slide 54

Slide 54 text

54 • ॱ൪Λकͬͯ΄͍͠Օॴ΁ద੾ʹࢦఆ͢Δ ΦʔμϦϯάΛࢦࣔ͢Δ͜ͱͰղܾ εϨουA ϊʔυૢ࡞ͯ͠ Χ΢ϯτ0ʹ͢Δ 👆
 ଞͷม਺ΞΫηεͷ
 ޙʹ࣮ߦ͍ͨ͠
 ʢ.releasingʣ 👆
 ଞͷม਺ΞΫηεͷ
 લʹ࣮ߦ͍ͨ͠
 ʢ.acquiringʣ precondition(_consumerCount.wrappingAdd(1, ordering: .acquiring)以下略) defer { _consumerCount.wrappingSubtract(1, ordering: .releasing) }

Slide 55

Slide 55 text

ϝϞϦΦʔμϦϯά 55 Swift Atomic*Ordering C++ std::memory_order S_Shimotoriͷཧղ .sequentiallyConsistent seq_cst Ϟσϧɿஞ࣍Ұ؏ੑ 
 ஗͍ .acquiringͱ.releasing acquireͱrelease ϞσϧɿϦϦʔεҰ؏ੑ .relaxed relaxed Ͳ͏ͳͬͯ΋ߏΘΜ .acquiringAndReleasingͱ͍͏ͷ΋͋ΔΑ ݫ͍͠ ΏΔ͍

Slide 56

Slide 56 text

ΦʔμϦϯάͷѻ͍ʹݫ͍͠࿩ • ϝιουͷorderingҾ਺ʹ͸σϑΥϧτ஋͕ͳ͍ • ͪΌΜͱ໌هͯ͠ίʔυϨϏϡʔʹ͔͚ͯ΄͍͠ • .sequentiallyConsistent͸஗͍ͷͰܰʑ͘͠࢖ͬͯ΄͘͠ͳ͍ • ΦʔμϦϯά͸ίϯύΠϧ࣌ఆ਺Ͱ౉͞ͳ͍ͱ͍͚ͳ͍ • ࣮ߦ࣌ʹܾ·Δ = switchจʹΑΔ෼ذ͕࢒Δ = ஗͘ͳΔ 56

Slide 57

Slide 57 text

ࠓ೔ͷ࿩୊ • 🦌ʮInt͔͠౉ͤͳ͍ΑͶʯɹ👈low levelͷ౎߹ • ͳΜ͔ݫ͘͠ͳ͍ʁɹ👈Φʔόʔϔουڐ͞Μ • ΦʔμϦϯάͬͯͳʹɹ👈ΦʔμϦϯάେࣄ & Φʔόʔϔουڐ͞Μ 57

Slide 58

Slide 58 text

·ͱΊ • ৭ʑͳख๏Ͱ҆શੑΛ֬อ͍ͯ͠Δʂ • AtomicͷαϯϓϧιʔείʔυΛॻ͘
 = ةݥͳঢ়گΛ࡞Γग़্ͨ͠ͰAtomicΛ࢖͏ ConcurrencyʮͦΜͳঢ়گ͸࡞Βͤͳ͍Αʂʯ
 S_ShimotoriʮͦΕ͡ΌࣸܦͰ͖ͳ͍͡ΌΜ🥺ʯ
 AtomicʮίϐʔͩΊʯ
 S_Shimotoriʮ͏Δ͍͞ͳ͋😡ʯ 58

Slide 59

Slide 59 text

p.s. Atomic͸Sendable͔൱͔

Slide 60

Slide 60 text

AtomicͱSendable • Conforms when Value conforms to Sendable and AtomicRepresentable. 60 let counter = Atomic(MyCounter(0)) DispatchQueue.concurrentPerform(iterations: 10) { _ in for _ in 0 ..< 1_000_000 { counter } } public struct MyCounter: AtomicRepresentable {...} Capture of 'counter' with non-sendable type 'Atomic' in a `@Sendable` closure

Slide 61

Slide 61 text

Atomic͕SendableͰ͋Δ͔Ͳ͏͔ • Value͕SendableͰɺ͔ͭAtomic͕ڥքӽ͑ʹ଱͑ΒΕΔ͔Ͳ͏͔…ʁ 61 ΋ͷʹΑΔ ʁʁʁ

Slide 62

Slide 62 text

SE-0410ʮελοΫϑϨʔϜ͕Ӡʑʯ • ʮSwift concurrency: Behind the scenesʯͷ࿩͔ɾɾʁ 62 https://developer.apple.com/videos/play/wwdc2021/10254/?time=960

Slide 63

Slide 63 text

func version1() async • ඇಉظؔ਺ͷݺͼग़͠φγͷ৔߹ 63 func version1() async { let counter = Atomic(0) let updatedCount = counter.load(...) } Stack … version1()ʹ͸
 தஅϙΠϯτ͕ͳ͍ͷͰ
 ྆ํͱ΋
 stackʹ͍Δ Heap … version1 ⚛︎︎

Slide 64

Slide 64 text

func version2() async • version2()͕caller͔Βݺ͹ΕΔ௚લ 64 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack (caller) Heap … … (caller)

Slide 65

Slide 65 text

func version2() async • version2()͕caller͔Βݺ͹Εͨ 65 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack version2 Heap … … (caller) (caller) ϛ version2 ⚛︎︎

Slide 66

Slide 66 text

func version2() async • version2()͕caller͔Βݺ͹Εͨ 66 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack version2 Heap … … (caller) version2 தஅϙΠϯτͷޙ͚ͩͳͷͰͬͪ͜ தஅϙΠϯτͷલޙͰ࢖ͬͯΔͷͰ ⚛︎︎

Slide 67

Slide 67 text

func version2() async • update()ΛݺΜͩ 67 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack update Heap … … (caller) version2 ϛ version2 update ⚛︎︎

Slide 68

Slide 68 text

func version2() async • update()͔Βversion2()ʹ໭͖ͬͯͨ 68 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack version2 Heap … … (caller) version2 ⚛︎︎

Slide 69

Slide 69 text

func version2() async • load()࡞ۀʹҠΔ 69 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack version2 Heap … … (caller) version2 load ⚛︎︎

Slide 70

Slide 70 text

func version2() async • load()ऴΘΓ 70 func version2() async { let counter = Atomic(0) let updater = Updater() await updater.update(counter) let updatedCount = counter.load(...) } Stack version2 Heap … … (caller) version2 ⚛︎︎

Slide 71

Slide 71 text

func version3() async 71 func version3() async { let counter = Atomic(0) let updater = Updater() await updater.doOtherWork() let updatedCount = counter.load(...) } Stack Heap … … version3 (caller) (caller) ϛ version3 ⚛︎︎ தஅϙΠϯτͷલޙͰ࢖ͬͯΔͷͰ

Slide 72

Slide 72 text

ͭ·Γʁ • Atomic͸ৗʹ୯Ұͷ҆ఆͨ͠ϝϞϦ্ͷ৔ॴʹ഑ஔ͞Ε͍ͯΔ • ͷͰʢʁʁʁʣɺத਎͕SendableͳΒAtomic΋ৗʹSendable • த਎͕SendableͳΒAtomic΋SendableͰ͍͍ͬ͠ΐɺAtomicࣗ਎͸ϝϞϦͷ ؍఺͔Βݟͯ΋໰୊ͳ͘ڥքΛӽ͑ΒΕΔ͔Βத਎࣍ୈ…ͱ͍͏࿩ʁ 72

Slide 73

Slide 73 text

·ͱΊɺͰ͸ͳ͘ॴײ • ΞτϛοΫͳΜͯͲ͏ͤLLVM͔CΛϥοϓͯ͠Δ͚ͩͩΖͬͯᢞΊͯ·ͨ͠ ຊ౰ʹਃ͠༁͋Γ·ͤΜͰͨ͠ • 5෼LTͱ͔Ͱશ༰ΛαΫοͱ঺հͯ͠ऴΘΔ૝ఆͩͬͨɾɾ 73

Slide 74

Slide 74 text

ࢀߟจݙ • What’s new in Swift - WWDC24 - Videos - Apple Developer • https://developer.apple.com/videos/play/wwdc2024/10136/ • Var of Atomic type is not an error? - #2 by MahdiBM - Using Swift - Swift Forums • https://forums.swift.org/t/var-of-atomic-type-is-not-an-error/69885/2 • ಉظ • https://www.hpcs.cs.tsukuba.ac.jp/~tatebe/lecture/h27/dsys/5-sync.pdf • ϝϞϦϞσϧೖ໳ʢSequential ConsistencyͱTotal Store OrderΛཧղ͢Δʣ • https://techblog.lycorp.co.jp/ja/20231216a • Swift ʹಋೖ༧ఆͷ Ownership ػೳͷ঺հ #swtws - Qiita • https://qiita.com/omochimetaru/items/c5f0eabde516e4713367 • How to develop SIL Optimizer in Swift Language • https://gist.github.com/freddi-kit/459297734b37cb51bfb08f74ce944cab • swift-ownership-jp/0176-enforce-exclusive-access-to-memory.md at master · omochi/swift-ownership-jp • https://github.com/omochi/swift-ownership-jp/blob/master/0176-enforce-exclusive-access-to-memory.md 74