แสดง nondeterminism ที่เป็นผลมาจากตัวกำหนดเวลาเธรด OS


10

ดังที่เราทราบกันดีว่าระบบปฏิบัติการที่ทันสมัยมีตัวจัดกำหนดการเธรดที่สามารถเลือกคำสั่งที่แตกต่างกันเพื่อกำหนดเวลาเธรดของคุณตามตรรกะภายในซึ่งรหัสของคุณไม่เป็นส่วนตัว โดยปกติแล้วคุณจะต้องออกแบบโค้ดแบบมัลติเธรดของคุณเพื่อให้แน่ใจว่าสิ่งที่ไม่คาดฝันนี้กำหนดไว้กับคุณจะไม่ส่งผลกระทบต่อผลลัพธ์ของคุณอย่างมีความหมาย

เป้าหมายที่นี่ตรงกันข้าม สร้างโปรแกรมที่พิมพ์จำนวนเต็มในช่วงเวลา [0,99] แต่ในลำดับที่จะแตกต่างจากการรันเพื่อรันเนื่องจากตัวกำหนดตารางเวลาเธรด OS

คุณต้องได้ "nondeterminism ที่เพียงพอ" ซึ่งนิยามไว้เป็น:

ใน 10 ชุดตามลำดับของการทดลอง 10 ครั้งโปรแกรมของคุณจะต้องผลิตอย่างน้อย 9 พีชคณิตที่ไม่ซ้ำกันในแต่ละการทดลอง คุณอาจมีจำนวนชุดการทดลองที่ล้มเหลวในจำนวนที่เหมาะสมทั้งสองด้านของ 10 ติดต่อกันซึ่งประสบความสำเร็จ

หรือหากต้องการกล่าวอีกวิธีหนึ่งคุณต้องใช้ 100 โปรแกรมของคุณซึ่งแต่ละบล็อกของการรัน 10 ครั้งมีการรันที่มากที่สุดสองรายการซึ่งให้ผลลัพธ์เหมือนกัน

ดังนั้นการสลับ 98 และ 99 จะไม่ตัด

นี่คือดังนั้นคำตอบที่ใช้จำนวนไบต์น้อยที่สุดชนะ

ข้อปลีกย่อย

  • เขียนเอาต์พุตของคุณไปยัง stdout หนึ่งรายการต่อบรรทัด
  • หากคุณรวมรูปแบบโดยให้ตัวอักษรสองตัวแทรกสอดระหว่างหัวข้อไปยัง stdout (แม้บางครั้ง) ทำให้เกิดสิ่งต่าง ๆ เช่นตัวเลขสามหลักหรือบรรทัดว่างผลลัพธ์ของคุณไม่ถูกต้อง
  • ข้อยกเว้นสำหรับกฎข้างต้นคือคุณสามารถปล่อยบรรทัดว่างเปล่าบรรทัดเดียวหลังจากพิมพ์หมายเลขที่ต้องการล่าสุด (ยินดีต้อนรับ)
  • หากคุณพลาดหรือทำซ้ำค่าที่ต้องการผลลัพธ์ของคุณจะไม่ถูกต้อง
  • โปรแกรมของคุณไม่จำเป็นต้องเป็น nondeterministic บนตัวประมวลผลหลักเดียว
  • โปรแกรมของคุณอาจใช้กรีนเธรด / เส้นใยซึ่งไม่ได้รับการจัดการโดยเคอร์เนลระบบปฏิบัติการจริงหากยังคงเป็นไปตามข้อกำหนดอื่น ๆ ของความท้าทายและระบบเธรดเป็นส่วนหนึ่งของภาษาของคุณหรือไลบรารีมาตรฐานสำหรับภาษาของคุณ
  • รันไทม์สำหรับโปรแกรมของคุณต้องเชื่อถือได้ภายใน 5 วินาทีบนโปรเซสเซอร์ที่ทันสมัย
  • คุณไม่ได้รับการระบุการเปลี่ยนแปลงสภาพแวดล้อมที่เกิดขึ้นนอกโปรแกรมของคุณเช่นรอหรือเปลี่ยนแปลงการตั้งค่า โปรแกรมของคุณควรผ่านการรัน 100ish ครั้งย้อนหลังหรือชั่วโมงระหว่างการรันแต่ละครั้งหรือ 100ish ครั้งในแบบคู่ขนาน (ซึ่งอาจช่วยได้จริง ... )
  • คุณสามารถใช้ตัวประมวลผลร่วมเช่น GPU หรือ Xeon Phi และกลไกการตั้งเวลาภายในของตัวเองสำหรับงาน กฎใช้กับสิ่งนี้เช่นเดียวกับที่ใช้กับเธรดสีเขียว
  • อย่าลังเลที่จะยั่วตารางเวลาด้วยวิธีการนอนหลับผลผลิตและลูกเล่นอื่น ๆ ตราบใดที่คุณทำตามกฎที่ระบุในโพสต์นี้

การดำเนินการที่ถูกแบน

nondeterminism แหล่งเดียวที่คุณได้รับอนุญาตให้วาดบนคือเมื่อตัวกำหนดตารางเวลากำหนดเธรดของคุณให้ทำงาน รายการต่อไปนี้ไม่ครบถ้วนสมบูรณ์มีวัตถุประสงค์เพื่อให้ตัวอย่างของสิ่งที่คุณไม่ได้รับอนุญาตให้ทำเนื่องจากพวกเขายอมรับแหล่งข้อมูลอื่น ๆ

  • การเข้าถึง PRNG หรือความสามารถของฮาร์ดแวร์ RNG โดยตรงหรือโดยอ้อม (เว้นแต่จะเป็นส่วนหนึ่งของกำหนดการ)
  • การอ่านอินพุตทุกชนิด (เวลาระบบระบบไฟล์เครือข่าย ฯลฯ )
  • การอ่าน ID เธรดหรือ ID กระบวนการ
  • การกำหนดตัวกำหนดตารางเวลาระบบปฏิบัติการเอง คุณต้องใช้ตัวกำหนดตารางเวลาระบบปฏิบัติการมาตรฐานจากระบบปฏิบัติการหลัก
  • ไม่อนุญาตให้กำหนดตัวกำหนดตารางเวลาเธรด / เส้นใยสีเขียว ซึ่งหมายความว่าหากคุณเขียนภาษาสำหรับความท้าทายนี้คุณต้องใช้ระบบปฏิบัติการเธรด

คำตอบการตรวจสอบ

คำตอบที่ดีกว่าน่าจะใช้ได้กับระบบปฏิบัติการทั่วไปและโปรเซสเซอร์ที่ทันสมัยทั้งหมดด้วยความรุ่งโรจน์ที่ได้รับการสนับสนุนตามสัดส่วนที่กว้าง อย่างไรก็ตามนี่ไม่ใช่ข้อกำหนดของการท้าทาย อย่างน้อยที่สุดคำตอบจะต้องรองรับโปรเซสเซอร์ SMP รุ่นใหม่หนึ่งตัวและระบบปฏิบัติการสมัยใหม่ ฉันจะทดสอบคำตอบที่นำไปสู่ความพร้อมของฮาร์ดแวร์ของฉัน

  • หากรายการของคุณจะไม่สร้างผลลัพธ์ที่ต้องการใน i7 5960x ที่รัน Windows 10 v1607 x64 ให้ระบุสภาพแวดล้อมที่ต้องการ
  • หากเป็นสิ่งที่ฉันสามารถสร้างซ้ำได้อย่างง่ายดายด้วย VMWare Workstation ให้ระบุรายละเอียด OS และ VM ที่แน่นอน
  • หากไม่สามารถผลิตได้ภายใต้เงื่อนไขเหล่านี้ให้บันทึกการจับภาพหน้าจอพร้อมกันของการทดสอบตามที่อธิบายไว้ในส่วนหัวและการบันทึกวิดีโอแบบใช้มือถือของหน้าจอของคุณด้วยการโต้ตอบระหว่างเมาส์และแป้นพิมพ์ของคุณ อุปกรณ์ใช้) มองเห็นได้ชัดเจนและโพสต์วิดีโอทั้งสองพร้อมกับคำตอบของคุณและรวมถึงคำอธิบายว่าทำไมมันถึงใช้งานได้
  • อีกทางหนึ่งคือรับผู้ใช้ที่เชื่อถือได้มานาน (ไม่ใช่คุณ) กับฮาร์ดแวร์ที่ตรงกันเพื่อสร้างผลลัพธ์และรับรองให้คุณ
  • หากรายการของคุณเป็นภาษาการเขียนโปรแกรมที่แปลกใหม่ที่นักพัฒนาทั่วไปจะไม่ถูกตั้งค่าให้คอมไพล์ / jit / ตีความให้คำแนะนำการตั้งค่า
  • หากรายการของคุณขึ้นอยู่กับรุ่นเฉพาะของล่าม JVM / Python / อื่น ๆ ให้ระบุว่า
  • หากใช้เวลานานกว่า 10 นาทีในการรัน back-to-back เพื่อรับชุดการทดลองตามลำดับ 10 ครั้งที่ประสบความสำเร็จในการทดสอบของฉันคุณล้มเหลว (ดังนั้นอย่าปล่อยให้สภาพความสำเร็จเป็นปรากฏการณ์ประหลาดโดยเฉพาะอย่างยิ่งถ้าคุณอยู่ใกล้ด้านบน รันไทม์ที่ถูกผูกไว้)

4
-1 สำหรับ "ถ้าฉันเบื่อ .... " ฉันจะบอกให้ระบุว่าต้องใช้เวลานานเท่าใด
Rɪᴋᴇʀ

@EasterlyIrk นอกจากนี้ยังกล่าวว่า 'น่าเชื่อถือต่ำกว่าห้าวินาทีบน CPU ที่ทันสมัย'
พาเวล

@Pavel ไม่ใช่สิ่งที่ฉันหมายถึง การทดลองที่ประสบความสำเร็จ 10 ครั้งไม่เกี่ยวข้องกับ 5 วินาที
Rɪᴋᴇʀ

@EasterlyIrk ยุติธรรมพอแล้วตอนนี้ 10 นาที
Techrocket9

@ Techrocket9 ยอดเยี่ยม downvote ถูกยกเลิก
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.

ฉันหวังว่าสิ่งนี้จะเป็นไปตามภารกิจ (ถ้าไม่โปรดแจ้งให้เราทราบ)

การทดสอบ:

เชลล์สคริปต์ที่ฉันใช้ทดสอบ nondeterminism ที่เพียงพอ:

#!/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 

คำแนะนำในการตั้งค่า:

ฉันทำการทดสอบด้วย Rakudo Perl 6 ล่าสุดบน Linux 64 บิตแม้ว่าฉันเดาว่ามันจะทำงานบนแพลตฟอร์มอื่น

หน้าดาวน์โหลด Rakudoมีคำแนะนำการติดตั้ง ฉันรวบรวมเหมืองจากคอมไพล์เช่นนี้

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

ลองออนไลน์:

หรือเพียงทดสอบออนไลน์โดยใช้ลิงก์ลอง It Online ที่ได้รับจาก @ b2gills ฉันตรวจสอบการทำงานสองสามครั้งและได้รับคำสั่งซื้อที่แตกต่างกันในแต่ละครั้ง แต่ยังไม่มีความอดทนที่จะเรียกใช้ 100 ครั้งผ่านอินเทอร์เฟซออนไลน์นั้น



ตรวจสอบความถูกต้องบน Windows 10 x64 บน i7 5960x ด้วย Rakudo Perl เวอร์ชั่น 2016.11
Techrocket9

4

bash, 32 28 ไบต์

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

ฉันวิ่ง 100 ครั้งและได้ผลลัพธ์ที่แตกต่าง 100

แก้ไข: บันทึกแล้ว 4 ไบต์ด้วย @DigitalTrauma


คุณเอาชนะฉันไป จริงๆแล้วของฉันจะสั้นกว่านิดหน่อยfor i in {0..99};{ echo $i&}แต่คุณโพสต์ก่อน - คุณสามารถรับมันได้ :)
Digital Trauma

นี่คือวิธีที่คุณสามารถทดสอบใน TIO นี่จะเป็นการรันสคริปต์ 10 ครั้งซึ่งจะจับเอาท์พุทจากการวิ่งแต่ละครั้งและจะทำการ md5ing เอาต์พุตจากการวิ่งแต่ละครั้ง เราสามารถเห็น md5s แตกต่างกันในแต่ละครั้ง md5s จะถูกจัดเรียงเพื่อให้มีการซ้ำซ้อนที่ชัดเจน
บาดเจ็บทางดิจิตอล

@DigitalTrauma ไม่มีเอกสาร แต่ดี!
Neil

1
ใช่ - มีเคล็ดลับสำหรับสิ่งนี้
บาดเจ็บทางดิจิทัล

สิ่งที่น่าสนใจคือสิ่งนี้ล้มเหลวในการบรรลุ "ความไม่เชื่องหมดเรี่ยวแรงที่มากพอ" เมื่อใช้งานใน bash-on-windows อย่างเป็นทางการของ Microsoft บน E5-2699 v4 แต่ทำงานใน RHEL Workstation VM ที่มี 4 คอร์บนเครื่องเดียวกัน
Techrocket9

2

PowerShell , 54 46 44 39 ไบต์

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

TIO PowerShell ไม่รองรับใน TIO ดังนั้นคุณจึงไม่สามารถลองใช้งานได้ที่นั่น ควรทำงานได้ดีบนเครื่อง Windows 10 ของคุณ :)

กำหนดฟังก์ชั่นpที่จะส่งออกรายการหมายเลขเมื่อเรียกใช้

การจับเวลา

การวิ่งครั้งเดียวเชื่อถือได้ในเวลาประมาณ 600ms บนเครื่องของฉัน การทดสอบ 100 ครั้งที่กำหนดไว้ด้านล่างเสร็จสิ้นภายในไม่กี่นาที

การทดสอบ

นี่คือรหัสที่สมบูรณ์เพื่อทดสอบ:

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

น่าสนใจนี่ใช้เวลา 51 วินาทีต่อการวิ่งบนกล่อง E5-2699 v4 ของฉัน แต่เพียง 0.7 วินาทีบนแล็ปท็อป i5-5200U ของฉัน มันบรรลุระดับความจำเป็นในการเข้าถึง nondeterminism บนแล็ปท็อปในขณะที่เข้ามาในเวลาไม่เกิน 5 วินาทีดังนั้นมันจึงผ่านไป เห็นได้ชัดว่าตัวจัดตารางเวลาของ PowerShell เล่นได้ไม่ดีกับแกนหลักและงานสั้น ๆ มากมาย
Techrocket9

และใช้เวลา 58 วินาทีใน i7 5960x
Techrocket9

อืม ... 74 วินาทีบนแล็ปท็อป i5-6300U อาจเป็นปัญหากับ Windows 10 หรือ PowerShell 5.1 เนื่องจาก i5-5200U เป็นเครื่องเดียวในบรรดาผู้ที่ผ่านการทดสอบและไม่ได้ใช้ Win10 (ใช้งาน 8.1)
Techrocket9

@ Techrocket9 แปลกฉันกำลังทดสอบ Win10, PS 5.1 ใน ISE แม้ว่า
ต้มตุ๋น

2

GCC บน Linux ขนาด 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จะส่งกลับค่ามากกว่าศูนย์ i--ในการปกครองสภาพห่วงเป็นเพียง


เหมือนกับคำตอบ bash กำหนดได้บน windows แต่ส่งผ่าน Linux (ในกรณีนี้คือ Debian)
Techrocket9
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.