OSスレッドスケジューラに起因する非決定性を公開する


10

誰もが知っているように、最新のオペレーティングシステムにはスレッドスケジューラがあり、コードが機密ではない内部ロジックに基づいてスレッドをスケジュールするためにさまざまな順序を選択できます。通常は、マルチスレッドコードを設計して、この非決定論が出力に意味のある影響を与えないようにします。

ここでの目標は反対です。[0,99]の間隔で整数を出力しますが、OSスレッドスケジューラにより実行ごとに異なる順序でプログラムを生成します。

次のように定義される「十分な非決定性」を達成する必要があります。

10試行の10の連続セットでは、プログラムは各試行内で少なくとも9の一意の順列を生成する必要があります。連続する10回の試行のいずれかの側で、成功する試行の失敗したセットが妥当な数になる可能性があります。

または、別の言い方をすると、プログラムの100回の実行が必要です。10回の実行の各ブロックには、同じものを出力する最大2回の実行があります。

したがって、98と99を時々入れ替えても、うまくいきません。

これはなので、使用するバイト数が最も少ない答えが優先されます。

細目

  • 出力をstdoutに書き込みます(1行に1エントリ)
  • 2つのスレッドにstdoutへの文字書き込みをインターリーブさせて(たまに)、3桁の数字や空の行などの結果が生じる場合、結果は無効です。
  • 上記のルールの唯一の例外は、最後に必要な数を出力した後、空の行を1行発行することです(どういたしまして)
  • 必要な値を見逃したり複製したりすると、結果は無効になります
  • プログラムは、シングルコアプロセッサで非決定的である必要ありませ(ただし、そうである場合は称賛されます)。
  • プログラムは、チャレンジの他の要件を満たし、スレッドシステムが言語または言語の標準ライブラリの一部である場合に限り、OSカーネルによって実際には管理されていない緑色のスレッド/ファイバーを使用できます。
  • プログラムのランタイムは、最新のプロセッサで5秒未満である必要があります。
  • 待機や設定変更など、プログラムの外部で発生する環境の変更を指定することはできません。プログラムは、100回連続して実行するか、各実行の間に1時間を置いて実行するか、並列に100回実行するかに合格する必要があります(これはおそらく実際に役立ちます...)
  • GPUやXeon Phiなどのコプロセッサーと、タスク用の独自の内部スケジューリングメカニズムを使用できます。ルールは、グリーンスレッドに適用されるのと同じ方法でこれに適用されます。
  • この投稿で指定されたルールに従っている限り、あらゆる種類のスリープ、イールド、その他のトリックでスケジューラを自由に挑発してください。

禁止されている操作

非決定論の唯一の原因は、スケジューラーがスレッドの実行をスケジュールするときです。次のリストは完全ではなく、非決定論の他のソースを認めているために許可されていないことの例を提供することのみを目的としています。

  • 任意の種類のPRNGまたはハードウェアRNG機能に直接または間接的にアクセスする(スケジューラーの固有の部分としての場合を除く)。
  • あらゆる種類の入力(システム時間、ファイルシステム、ネットワークなど)の読み取り
  • スレッドIDまたはプロセスIDの読み取り
  • OSスケジューラのカスタマイズ。メインストリームOSの標準OSスケジューラを使用する必要があります
  • グリーンスレッド/ファイバースケジューラのカスタマイズも禁止されています。つまり、この課題に対応する言語を作成する場合、OSスレッドを使用する必要あります。

回答の検証

できれば答えはすべての一般的なOSと最新のプロセッサで機能し、サポートの幅に比例して賞賛が与えられます。ただし、これは課題の要件ではありません。少なくとも、回答は1つの最新のSMPプロセッサと最新のOSをサポートする必要があります。ハードウェアの可用性の範囲で主要な回答をテストします。

  • 入力がWindows 10 v1607 x64を実行しているi7 5960xで必要な出力を生成しない場合は、必要な環境を指定します
  • VMWare Workstationで簡単に再現できるものであれば、正確なOSとVMの仕様を提供してください
  • これらの条件のいずれかで作成できない場合は、ヘッダーセクションで説明されているように、テストの同時画面キャプチャと、マウスとキーボードの操作(または非標準の計算による制御スキーム)による画面のハンドヘルドビデオ録画を記録します。デバイスの使用)両方の動画を明確に表示し、回答と一緒に投稿し、それが機能する理由の説明を含める
  • または、一致するハードウェアを使用して信頼できる長年のユーザー(あなたではない)に結果を再現し、保証します
  • エントリがエキゾチックなプログラミング言語であり、一般的な開発者がコンパイル/ jit /解釈するように設定されていない場合は、設定手順を提供します
  • エントリーがJVM / Pythonインタープリター/その他の特定のバージョンに依存している場合は、どれを指定するか
  • 私のテストで10回の連続した一連の試行が成功するまでに10分以上かかる場合、失敗します(特に、上限に近い場合は、成功条件が異常な発生にならないようにしてください)ランタイムバインド)

4
「退屈したら...」の場合は-1。私はそれがかかることができる時間を正確に指定すると思います。
Rɪᴋᴇʀ

@EasterlyIrkまた、「確実に近代的なCPUの5秒の下に」と言う
パベル

@Pavelそれは私が言及しているものではありません。成功した10回のトライアルは5秒とは関係ありません。
Rɪᴋᴇʀ

@EasterlyIrk結構です、今では10分です。
Techrocket9 2017年

@ Techrocket9クールな反対投票は取り消されました。
Rɪᴋᴇʀ

回答:


4

Perl 6、27バイト

await map {start .say},^100

説明:

      map {          },^100  # Iterate over the range 0..99, and for each of number:
           start             # Send the following task to a thread pool of OS threads:
                 .say        # Print the number, followed by a newline.
await                        # Wait until all tasks have completed.

これで問題が解決することを願っています。(そうでない場合は、お知らせください)。

テスト:

十分な非決定性をテストするために使用したシェルスクリプト:

#!/usr/bin/bash
for i in {1..10}; do
    set=""
    for j in {1..10}; do
        set="${set}$(perl6 nondet.p6 | tr '\n' ',')\n"
    done
    permutations="$(echo -e "$set" | head -n -1 | sort | uniq | wc -l)"
    echo -n "$permutations "
done

私にとって、これは出力します:

10 10 10 10 10 10 10 10 10 10 

セットアップ手順:

私は64ビットLinuxで最新のRakudo Perl 6を使用してテストを実行しましたが、他のプラットフォームでも動作すると思います。

Rakudoのダウンロードページには、セットアップ手順があります。私は次のようにgitから私のものをコンパイルしました:

git clone git@github.com:rakudo/rakudo.git
cd rakudo
perl Configure.pl --gen-moar --make-install
export PATH="$(pwd)/install/bin/:$PATH"

オンラインでお試しください:

または、@ b2gillsが提供するこのTry It Onlineリンクを使用し、オンラインでテストしてください。私は数回実行を確認し、毎回異なる注文を得ましたが、そのオンラインインターフェースで100回実行するための忍耐力がありませんでした。



Rakudo Perlバージョン2016.11を搭載したi7 5960x上のWindows 10 x64で検証
Techrocket9

4

bash、32 28バイト

for i in {0..99};{ echo $i&}

私はこれを100回実行し、100の異なる結果を得ました。

編集:@DigitalTraumaのおかげで4バイトが節約されました。


あなたは私をそれに負けました。実際、私のものは少し短いですがfor i in {0..99};{ echo $i&}、最初に投稿しました-あなたはそれを取ることができます:)
Digital Trauma

TIOでテストする方法は次のとおりです。これはスクリプトの10回の実行を行い、各実行からの出力をキャプチャし、各実行からの出力をmd5します。md5が毎回異なることがわかります。md5は、潜在的な重複を明らかにするためにソートされます。
デジタルトラウマ

@DigitalTrauma文書化されていませんがいいです!
Neil

1
うん-これにはヒントがあります。
デジタルトラウマ

興味深いことに、これはE5-2699 v4上のMicrosoftの公式bash-on-windowsで実行すると「十分な非決定性」を達成できませんが、同じマシンに4つのコアを持つRHEL Workstation VMで動作するため、通過します。
Techrocket9 2017年

2

PowerShell54 46 44 39バイト

workflow p{foreach -p($i in 0..99){$i}}

PowerShellワークフローはTIOではサポートされていないため、そこで試すことはできません。ただし、Windows 10マシンでうまく機能するはずです:)

p呼び出されたときに数値のリストを出力する関数を定義します。

タイミング

私のマシンでは、1回の実行で確実に約600msで実行されます。以下に定義する100個のテストは2分未満で終了します。

テスト中

これをテストする完全なコードは次のとおりです。

workflow p{foreach -p($i in 0..99){$i}}
#workflow p{foreach($i in 0..99){$i}}
# uncomment above to prove testing methodology does detect duplicates

1..10 | % {
    $set = $_
    Write-Host "Set $set of 10"
    1..10 | % -b {
        $runs = @()
    } -p {
        $run = $_
        Write-Host "-- Run $run of 10 in set $set"
        $runs += "$(p)"
    } -e {
        Write-Host "-- There were $(10-($runs|Get-Unique).Count) duplicate runs in set $set"
    }
}

私のマシンでの出力:

Set 1 of 10
-- Run 1 of 10 in set 1
-- Run 2 of 10 in set 1
-- Run 3 of 10 in set 1
-- Run 4 of 10 in set 1
-- Run 5 of 10 in set 1
-- Run 6 of 10 in set 1
-- Run 7 of 10 in set 1
-- Run 8 of 10 in set 1
-- Run 9 of 10 in set 1
-- Run 10 of 10 in set 1
-- There were 0 duplicate runs in set 1
Set 2 of 10
-- Run 1 of 10 in set 2
-- Run 2 of 10 in set 2
-- Run 3 of 10 in set 2
-- Run 4 of 10 in set 2
-- Run 5 of 10 in set 2
-- Run 6 of 10 in set 2
-- Run 7 of 10 in set 2
-- Run 8 of 10 in set 2
-- Run 9 of 10 in set 2
-- Run 10 of 10 in set 2
-- There were 0 duplicate runs in set 2
Set 3 of 10
-- Run 1 of 10 in set 3
-- Run 2 of 10 in set 3
-- Run 3 of 10 in set 3
-- Run 4 of 10 in set 3
-- Run 5 of 10 in set 3
-- Run 6 of 10 in set 3
-- Run 7 of 10 in set 3
-- Run 8 of 10 in set 3
-- Run 9 of 10 in set 3
-- Run 10 of 10 in set 3
-- There were 0 duplicate runs in set 3
Set 4 of 10
-- Run 1 of 10 in set 4
-- Run 2 of 10 in set 4
-- Run 3 of 10 in set 4
-- Run 4 of 10 in set 4
-- Run 5 of 10 in set 4
-- Run 6 of 10 in set 4
-- Run 7 of 10 in set 4
-- Run 8 of 10 in set 4
-- Run 9 of 10 in set 4
-- Run 10 of 10 in set 4
-- There were 0 duplicate runs in set 4
Set 5 of 10
-- Run 1 of 10 in set 5
-- Run 2 of 10 in set 5
-- Run 3 of 10 in set 5
-- Run 4 of 10 in set 5
-- Run 5 of 10 in set 5
-- Run 6 of 10 in set 5
-- Run 7 of 10 in set 5
-- Run 8 of 10 in set 5
-- Run 9 of 10 in set 5
-- Run 10 of 10 in set 5
-- There were 0 duplicate runs in set 5
Set 6 of 10
-- Run 1 of 10 in set 6
-- Run 2 of 10 in set 6
-- Run 3 of 10 in set 6
-- Run 4 of 10 in set 6
-- Run 5 of 10 in set 6
-- Run 6 of 10 in set 6
-- Run 7 of 10 in set 6
-- Run 8 of 10 in set 6
-- Run 9 of 10 in set 6
-- Run 10 of 10 in set 6
-- There were 0 duplicate runs in set 6
Set 7 of 10
-- Run 1 of 10 in set 7
-- Run 2 of 10 in set 7
-- Run 3 of 10 in set 7
-- Run 4 of 10 in set 7
-- Run 5 of 10 in set 7
-- Run 6 of 10 in set 7
-- Run 7 of 10 in set 7
-- Run 8 of 10 in set 7
-- Run 9 of 10 in set 7
-- Run 10 of 10 in set 7
-- There were 0 duplicate runs in set 7
Set 8 of 10
-- Run 1 of 10 in set 8
-- Run 2 of 10 in set 8
-- Run 3 of 10 in set 8
-- Run 4 of 10 in set 8
-- Run 5 of 10 in set 8
-- Run 6 of 10 in set 8
-- Run 7 of 10 in set 8
-- Run 8 of 10 in set 8
-- Run 9 of 10 in set 8
-- Run 10 of 10 in set 8
-- There were 0 duplicate runs in set 8
Set 9 of 10
-- Run 1 of 10 in set 9
-- Run 2 of 10 in set 9
-- Run 3 of 10 in set 9
-- Run 4 of 10 in set 9
-- Run 5 of 10 in set 9
-- Run 6 of 10 in set 9
-- Run 7 of 10 in set 9
-- Run 8 of 10 in set 9
-- Run 9 of 10 in set 9
-- Run 10 of 10 in set 9
-- There were 0 duplicate runs in set 9
Set 10 of 10
-- Run 1 of 10 in set 10
-- Run 2 of 10 in set 10
-- Run 3 of 10 in set 10
-- Run 4 of 10 in set 10
-- Run 5 of 10 in set 10
-- Run 6 of 10 in set 10
-- Run 7 of 10 in set 10
-- Run 8 of 10 in set 10
-- Run 9 of 10 in set 10
-- Run 10 of 10 in set 10
-- There were 0 duplicate runs in set 10

興味深いことに、これは私のE5-2699 v4ボックスでは実行ごとに51秒かかりますが、i5-5200Uラップトップでは0.7秒しかかかりません。ラップトップで必要な非決定性の程度を最大5秒未満で達成しているため、合格です。どうやら、PowerShellのスケジューラーは、多くのコアや短いタスクではうまく機能しません。
Techrocket9 2017年

そしてi7 5960xで58秒かかります
Techrocket9

うーん... i5-6300Uラップトップで74秒。Win10を実行していない(8.1を実行している)テスト済みのマシンの中でi5-5200Uが唯一のマシンであるため、Windows 10またはPowerShell 5.1の問題かもしれません。
Techrocket9 2017年

@ Techrocket9奇妙なことに、私はWin10、PS 5.1でテストしていました。でもISEでは。
ブライアンティスト、2017年

2

LinuxのGCC、47バイト

main(i){for(i=99;fork()?i--:!printf("%d\n",i););}

これにより、gccバージョン4.9.2(フラグなし)でコンパイルされたため、ほぼ毎回異なる結果が得られました。具体的には、64ビットのDebian 8.6(カーネルバージョン3.16.31)を使用していました。

説明

fork()がゼロ(子プロセス)を返す場合、の値iが出力され、printfはゼロより大きい値を返すため、ループ条件はfalse です。親プロセスでは、ループ条件はただi--です。


bashの回答と同じです。Windowsでは確定的ですが、Linux(この場合はDebian)では合格です。
Techrocket9 2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.