Rubyの並列性におけるパターンの導入


先日キールによって面白い引用があった.

"We’ll need to push the Ruby ecosystem to have less shared
state to fully leverage the Ractor pattern"
via


...とpiotrから別の興味深いスレッド:

...is a message I've been trying to convey too (-
the ractor part of course) for the past ~6 years or so,
but people would mostly look at me with confusion

via


今Peotrを知らないあなたのために、彼はDryRBの後の人々のうちの1人です.私は直接この記事でDryrbをカバーしていません、しかし、私はあなたがその方向で考えることを得るために若干の基盤をセットしたいです.
私たちは、並列性の性質を見て、それが多くの便利で来るいくつかのパターンで見ます.
あなたがこの記事の考えにより気まぐれな導入を望むならば、私は提案します.

数値を追加する
私は、しばらくの間、一緒に数を加える性質を考慮して欲しいです:
1 + 1
# => 2
基本的なものとして、それは直感的に知っているかもしれませんが、彼らはすべての自分の名前を知っていない可能性がありますいくつかの非常に興味深いパターンを隠している.速いパターンを見てみましょう.

数のパターン

パターン1.数値の追加
これから始めましょう:2つの整数を一緒に加えると、別の整数を取り戻そうとします.
(1 + 1).class
# => Integer
整数とは関係ありません.+と組み合わせると、整数値を返します.

パターン2数値へのゼロの加算
あなたが他の数にゼロを加えるならば、あなたはその同じ数を取り戻すでしょう:
1 + 0
# => 1

パターン3.Parensを持つグループの番号は結果を変更しません
そこにいくつかの親をドロップする場合は、同じ結果を得る予定です.
1 + 2 + 3 == (1 + 2) + 3
(1 + 2) + 3 == 1 + (2 + 3)

パターン4.数の負の加算はゼロを返す
私たちがどんな数の否定的なバージョンも我々自身に加えるならば、我々はゼロを取り戻そうとしています:
1 + -1 == 0

パターン5.実際、順序は問題ではない
確かに、私たちは親との数字をグループ化することができ、同じことを得ることができますが、私たちは本当に注文を気にする必要はありません.
1 + 2 + 3 == 3 + 2 + 1
3 + 2 + 1 == 1 + 3 + 2

パターンが規則となる
では、なぜ正確にこの問題の原因は何ですか?いくつかのすべての直感的な感覚のように思えるかもしれない我々は数年後に数学のクラスで取り上げた.
これらのパターンはいくつかのルールの基礎です.彼らを見て、彼らに名前を与えましょう.

規則1.閉鎖
関数を返す関数からのクロージャについて知っているかもしれませんが、それは私たちが行っていることではありません.
つの数字を加えることは、私たちのケースの数、または整数を返すことを覚えておいてください.
整数は数学で、値の集合です.セット内の2つの値を組み合わせて、それが同じセットでアイテムをあなたに与えるならば、それは「セットの上に閉じられた」、または閉鎖であると考えられます.
それは、同じタイプの何かを返します.
この規則が働くには、いくつかのことが必要です.
  • 値の集合(整数)
  • 一緒に結合する方法(+)
  • それらに加わる
  • は、その同じセットの値(整数)
  • で何かを返します

    規則2.アイデンティティ
    Identityは、その正確な同じ値を戻すために、セット内の他の値と組み合わせることができる値です.
    それは「空の」値です.加算の場合、ゼロ:
    1 + 0 == 0 + 1
    0 + 1 == 1
    
    しかし、この値は2つの数値を追加しているという事実に依存します.私たちが代わりにそれらを掛けて、我々の結合方法としてそれを使用するならば、我々には問題があるでしょう:
    1 * 0
    # => 0
    
    演算子を変更すると、ID要素が何であるかを変更することもできます.乗算のためには、
    1 * 1
    # => 1
    

    規則3.結合性
    結合性は、グループ化プロパティです.つまり、3つ以上の数でグループをグループ化して、どこでも好きな場所でグループ化することができます.
    1 + 2 + 3 == (1 + 2) + 3
    (1 + 2) + 3 == 1 + (2 + 3)
    

    規則4.反転
    すべての値の反転手段を使用すると、空、またはアイデンティティに戻るには、それの反転バージョンに参加することができます参加する.加えて、n-nによって整数で否定されることができます.
    1 + -1 == 0
    5 + -5 == 0
    
    それは整数を掛けるのにそれほどよく働きません、nによって掛け算を反転させるために、あなたは整数でない1/nによって乗らなければならないでしょう.乗算は、このルールで動作しないように見えます.

    規則5.コミュニケーション
    commutitivityとは、同じ結果を返すメソッドが同じ値である場合には、順序が問題でないことを意味します.
    1 + 2 + 3 == 3 + 2 + 1
    
    あなたがそれを試みるならば、乗算のために同じ働きます:
    1 * 2 * 3 == 3 * 2 * 1
    

    パターンはどこでも
    それで、なぜ、あなたが尋ねるかもしれない関連のどれでもありますか?
    もっと速い型を試してみましょう.

    文字列加算

  • 閉鎖:+

  • アイデンティティ:""

  • アソシエーション:"a" + "b" + "c" == ("a" + "b") + "c"

  • アレイ追加

  • 閉鎖:+

  • アイデンティティ:[]

  • アソシエーション:[1] + [2] + [3] == [1, 2] + 3

  • ハッシュマージ

  • 閉鎖:merge

  • アイデンティティ:{}

  • アソシエーション:{ a: 1 }.merge({ b: 1 }).merge({ c: 1 }) == { a: 1, b: 1 }).merge({ c: 1 })

  • 関数

  • 閉鎖:<<

  • アイデンティティ:-> v { v }

  • アソシエーション:a << b << c == (a << b) << c

  • クエリのクエリ

  • 閉鎖:.

  • アイデンティティ:all

  • アソシエーション:Model.where(**a).where(**b).where(**c) == Model.where(**a, **b).where(**c)

  • 頻繁なパターンは名前が付く傾向がある
    待って待って、それは多くのように思える!よく、何かが起こるとき、我々はその概念に名前を与える傾向があります.
    そのパターンがクロージャ、アイデンティティ、および結合性の規則に一致する場合には、我々はそれをモノイドと呼びます.
    反転を加えるとグループになります.そして、私たちも交信性を加えると、それはアーベル群になります.(This listing of Group-like structures may be useful)
    Rubyでは、これらのパターンを「還元可能」と呼びます.
    # values           identity       joining
    #    V                 V             V
    [1, 2, 3, 4, 5].reduce(0) { |a, i| a + i }
    
    %w(some words here to join).reduce('') { |a, s| a + s }
    
    [[1], [2], [3]].reduce([]) { |a, v| a + v }
    
    どれが素晴らしいですが、なぜこのような並列性に関連するのですか?
    それらの概念のどれも機能するために変更可能な状態に依存しないので.

    並列化
    バッチシステムで数十億の数字があったとしましょう.私たちは、その数が追加に加わったとき、いくつかの本当に良い利点を与えるアベルグループのプロパティを持っていることを知っています
  • 私たちは何千ものコンピュータ、秩序の不可逆の中で何でもチャンクすることができます.
  • 私たちは、偶数だけにフィルターをかけることができます.それがすべての数をフィルターにかけるならば、我々はちょうど代わりにゼロを返します.
  • 私たちがバッチが悪いことを知っているならば、我々はそれを元に戻すためにそれらの数字ns.map { |v| -v }の逆バージョンを再送できます.
  • これらのパターンを知ることは、非同期または並列システムで動作する方法について直観を示します、そして、彼らは特に俳優モデルのために本当に危険にさらされることができます.

    結果が欲しい
    素晴らしいが、あなたの仕事は、数字を追加するよりも必要があります.それはパーティーのための素晴らしいトリックだが、我々は深刻なプログラマの仕事をしないでください?
    DryRBには興味深い概念があり、Result(ちょっとクリックして待つ)という概念があります.
    def greater_result(a, b)
        a > b ? Success(a) : Failure('Error!')
    end
    
    greater_result(1, 2).fmap { |v| v + 10 }
    # => Failure('Error!')
    
    greater_result(3, 2).fmap { |v| v + 10 }
    # => Success(13)
    
    それは私たちが成功または失敗の異なった考えを表すのを許して、私たちのために若干の重要なクラスにそれらを包みます.トリック?SuccessFailureまたはfmapのような全体の多くを見て、何かをjoinのセットで返します.正確にこれらの上に私たちの不愉快な小さなモノイドを超えていくつかの手順を行くため.+Resultを呼び出したならば、fmapの場合、それは我々を無視します.つまり、パラレルワールドでエラーを処理する安全な方法があります.
    あなたは、リンクがmonadsに言及するのに気づくかもしれません.あなたは、むしろ前に、むしろ怪奇な「モナドは、内部機能家のカテゴリーの単体です」と聞いたかもしれません.
    全体の概念としてのモナドを無視して、彼らはモノイドといくつかのエキストラと同じパターンに従ってください.つまり、私たちは同じ利点を得ることを意味します.つまり、Successは並列システムでは安全です.
    DryRBはこれらのタイプの多くを導入します、そして、もちろん、それは我々が使用しているものからのストレッチです、しかし、我々が我々が公平なゲーム領域にいるように、それはractorsです.我々が遊ぶ方法を変える時間です.

    ラッピング
    追加のリソースについては、Rubyを使用してパラレルな世界で可能なことについていくつかのアイデアを構築し続けるように、ここからRailway Oriented Programmingを強く提案します.
    上のあのビデオ?また、モノイドについて言及することなくモノイドについての話で、それは楽しいトリックでした.場合は、現在見ているパターンを見つけることができます参照してください!
    ここに多くのことがあります、そして、私は後でこの上でより詳細なポストを作るかもしれません、しかし、それにもかかわらず、多くの楽しいこと.
    ある日、私はちょうどmonadチュートリアルを書くかもしれません、しかし、今日、私は考えません.