Phơi bày chủ nghĩa không xác định kết quả từ bộ lập lịch xử lý luồng của hệ điều hành


10

Như chúng ta đã biết, các hệ điều hành hiện đại có các bộ lập lịch luồng có thể chọn các đơn đặt hàng khác nhau để lên lịch cho các luồng của bạn dựa trên logic bên trong mà mã của bạn không thuộc về. Thông thường, bạn thiết kế mã đa luồng của mình để đảm bảo rằng tính không đặc biệt này áp đặt lên bạn không ảnh hưởng một cách có ý nghĩa đến đầu ra của bạn.

Mục tiêu ở đây là ngược lại. Tạo một chương trình in các số nguyên trong khoảng [0,99] nhưng theo thứ tự sẽ thay đổi từ chạy sang chạy do bộ lập lịch xử lý luồng của hệ điều hành.

Bạn phải đạt được "đủ điều kiện không xác định", được định nghĩa là:

Trong 10 bộ liên tiếp gồm 10 thử nghiệm, chương trình của bạn phải tạo ra ít nhất 9 hoán vị duy nhất trong mỗi thử nghiệm. Bạn có thể có một số lượng hợp lý các thử nghiệm thất bại ở hai bên của 10 lần liên tiếp thành công.

Hoặc, nói cách khác, bạn cần 100 lần chạy chương trình trong đó mỗi khối 10 lần chạy có nhiều nhất hai lần chạy cùng một thứ.

Vì vậy, đôi khi hoán đổi 98 và 99 sẽ không cắt nó.

Đây là một , vì vậy câu trả lời sử dụng ít byte nhất sẽ thắng.

Minutiae

  • Viết đầu ra của bạn vào thiết bị xuất chuẩn, một mục nhập trên mỗi dòng
  • Nếu bạn quản lý định dạng bằng cách có hai luồng ký tự xen kẽ ghi vào thiết bị xuất chuẩn (thậm chí đôi khi) dẫn đến những thứ như số có ba chữ số hoặc dòng trống, kết quả của bạn không hợp lệ
  • Ngoại lệ duy nhất cho quy tắc trên là bạn có thể phát ra một dòng trống duy nhất sau khi in số bắt buộc cuối cùng (bạn được chào đón)
  • Nếu bạn bỏ lỡ hoặc sao chép bất kỳ giá trị bắt buộc nào, kết quả của bạn không hợp lệ
  • Chương trình của bạn không cần phải không xác định trên một bộ xử lý lõi đơn (mặc dù là kudos)
  • Chương trình của bạn có thể sử dụng các luồng / sợi màu xanh lá cây không thực sự được quản lý bởi nhân hệ điều hành. Nó vẫn đáp ứng các yêu cầu khác của thử thách và hệ thống luồng là một phần của ngôn ngữ hoặc thư viện chuẩn cho ngôn ngữ của bạn
  • Thời gian chạy cho chương trình của bạn phải đáng tin cậy dưới 5 giây trên bộ xử lý hiện đại
  • Bạn không được chỉ định các thay đổi đối với môi trường xảy ra bên ngoài chương trình của mình, chẳng hạn như chờ đợi hoặc thay đổi cài đặt; chương trình của bạn sẽ vượt qua cho dù chạy 100 lần trở lại hoặc với một giờ giữa mỗi lần chạy hoặc 100 lần song song (điều đó có thể thực sự giúp ích ...)
  • Bạn có thể sử dụng bộ đồng xử lý như GPU hoặc Xeon Phi và cơ chế lập lịch trình nội bộ của riêng nó cho các tác vụ. Các quy tắc áp dụng cho điều này giống như cách họ áp dụng cho các chủ đề màu xanh lá cây.
  • Vui lòng khiêu khích người lập lịch với tất cả các cách ngủ, sản lượng và các thủ thuật khác miễn là bạn tuân thủ các quy tắc được chỉ định trong bài đăng này

Hoạt động cấm

Nguồn duy nhất của thuyết không điều kiện mà bạn được phép rút ra là khi trình lập lịch biểu lập lịch trình các chủ đề của bạn để chạy. Danh sách sau đây không đầy đủ, chỉ nhằm mục đích cung cấp các ví dụ về những điều bạn không được phép làm khi họ thừa nhận các nguồn khác của thuyết không điều kiện.

  • Truy cập trực tiếp hoặc gián tiếp vào bất kỳ loại khả năng RNG PRNG hoặc phần cứng nào (trừ khi nó là một phần vốn có của bộ lập lịch).
  • Đọc trong bất kỳ loại đầu vào nào (thời gian hệ thống, hệ thống tập tin, mạng, v.v.)
  • Đọc ID luồng hoặc ID tiến trình
  • Tùy chỉnh bộ lập lịch hệ điều hành; bạn phải sử dụng bộ lập lịch hệ điều hành tiêu chuẩn từ hệ điều hành chính
  • Tùy chỉnh lịch trình sợi / sợi màu xanh lá cây của bạn cũng bị cấm. Điều này có nghĩa là nếu bạn viết một ngôn ngữ cho thử thách này, bạn phải sử dụng các luồng của hệ điều hành.

Xác nhận câu trả lời

Tốt nhất là một câu trả lời sẽ hoạt động trên tất cả các hệ điều hành phổ biến và bộ xử lý hiện đại, với danh hiệu được trao tỷ lệ thuận với độ rộng của hỗ trợ. Tuy nhiên, đây không phải là một yêu cầu của thách thức. Tối thiểu một câu trả lời phải hỗ trợ một bộ xử lý SMP hiện đại và HĐH hiện đại. Tôi sẽ kiểm tra các câu trả lời hàng đầu trong phạm vi khả dụng phần cứng của tôi.

  • Nếu mục nhập của bạn sẽ không tạo ra đầu ra cần thiết trên i7 5960x chạy Windows 10 v1607 x64, hãy chỉ định môi trường cần thiết
  • Nếu đó là thứ tôi có thể dễ dàng sao chép bằng VMWare Workstation, hãy cung cấp thông số kỹ thuật cho hệ điều hành và VM chính xác
  • Nếu không thể được sản xuất trong một trong các điều kiện đó, hãy ghi lại bản chụp màn hình đồng thời của bài kiểm tra như được mô tả trong phần tiêu đề và bản ghi video cầm tay của màn hình với sự tương tác giữa chuột và bàn phím của bạn (hoặc bất kỳ sơ đồ điều khiển nào tính toán không chuẩn của bạn sử dụng thiết bị) hiển thị rõ ràng và đăng cả hai video cùng với câu trả lời của bạn và bao gồm giải thích lý do tại sao nó hoạt động
  • Cách khác, hãy lấy một người dùng lâu năm có uy tín (không phải là bạn) với phần cứng phù hợp để tái tạo kết quả và chứng từ cho bạn
  • Nếu mục nhập của bạn bằng ngôn ngữ lập trình kỳ lạ mà nhà phát triển thông thường sẽ không được thiết lập để biên dịch / jit / phiên dịch, hãy cung cấp hướng dẫn thiết lập
  • Nếu bạn nhập tùy thuộc vào một phiên bản cụ thể của trình thông dịch JVM / Python / khác, hãy xác định
  • Nếu phải mất hơn 10 phút chạy ngược lại để có được 10 thử nghiệm liên tiếp thành công trong thử nghiệm của tôi thì bạn đã thất bại (vì vậy đừng để điều kiện thành công xảy ra, đặc biệt là nếu bạn ở gần phía trên thời gian chạy bị ràng buộc)

4
-1 cho "Nếu tôi chán ....". Tôi muốn nói chính xác phải mất bao lâu.
Rɪᴋᴇʀ

@EasterlyIrk Nó cũng nói 'đáng tin cậy dưới năm giây trên một CPU hiện đại'
Pavel

@Pavel đó không phải là những gì tôi đang đề cập đến. 10 thử nghiệm thành công không liên quan đến 5 giây.
Rɪᴋᴇʀ

@EasterlyIrk Đủ rồi, bây giờ là 10 phút.
Techrocket9

@ Techrocket9 mát mẻ, downvote bị hủy bỏ.
Rɪᴋᴇʀ

Câu trả lời:


4

Perl 6 , 27 byte

await map {start .say},^100

Giải trình:

      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.

Tôi hy vọng điều này đáp ứng nhiệm vụ. (Nếu không, vui lòng cho tôi biết).

Kiểm tra:

Kịch bản shell tôi đã sử dụng để kiểm tra đủ tính không phá hủy:

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

Đối với tôi, kết quả này:

10 10 10 10 10 10 10 10 10 10 

Hướng dẫn cài đặt:

Tôi đã chạy thử nghiệm với Rakudo Perl 6 cập nhật trên 64bit Linux, mặc dù tôi đoán nó sẽ hoạt động trên các nền tảng khác.

Các trang download Rakudo có hướng dẫn cài đặt. Tôi đã biên dịch của tôi từ git như thế này:

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

Dùng thử trực tuyến:

Hoặc chỉ kiểm tra trực tuyến, sử dụng liên kết Dùng thử trực tuyến này được cung cấp bởi @ b2gills. Tôi đã kiểm tra một vài lần chạy và nhận được một đơn đặt hàng khác nhau mỗi lần, nhưng không đủ kiên nhẫn để chạy nó 100 lần qua giao diện trực tuyến đó.



Được xác thực trên Windows 10 x64 trên i7 5960x với phiên bản Rakudo Perl 2016.11
Techrocket9

4

bash, 32 28 byte

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

Tôi đã chạy 100 lần và nhận được 100 kết quả khác nhau.

Chỉnh sửa: Đã lưu 4 byte nhờ @DigitalTrauma.


Bạn đánh bại tôi vào nó. Trên thực tế của tôi ngắn hơn một chút for i in {0..99};{ echo $i&}, nhưng bạn đã đăng lên trước - bạn có thể lấy nó :)
Chấn thương kỹ thuật số

Đây là một cách bạn có thể kiểm tra nó trong TIO. Điều này thực hiện 10 lần chạy tập lệnh, thu được đầu ra từ mỗi lần chạy, chúng md5ing đầu ra từ mỗi lần chạy. Chúng ta có thể thấy md5s khác nhau mỗi lần. Các md5 được sắp xếp để làm cho các bản sao tiềm năng rõ ràng.
Chấn thương kỹ thuật số

@DigitalTrauma Không có giấy tờ nhưng tốt đẹp!
Neil

1
Đúng - có một mẹo cho việc này.
Chấn thương kỹ thuật số

Điều thú vị là, điều này không đạt được "đủ điều kiện không tồn tại" khi chạy trong bash-on-windows chính thức của Microsoft trên E5-2699 v4, nhưng nó hoạt động trong máy ảo RHEL Workstation với 4 lõi trên cùng một máy để nó vượt qua.
Techrocket9

2

PowerShell , 54 46 44 39 byte

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

Quy trình làm việc PowerShell không được hỗ trợ trong TIO, vì vậy bạn không thể thử ở đó. Nên hoạt động tốt trên máy Windows 10 của bạn :)

Xác định một hàm psẽ xuất ra danh sách các số khi được gọi.

Thời gian

Một lần chạy đáng tin cậy chạy trong khoảng 600ms trên máy của tôi. 100 bài kiểm tra được xác định dưới đây kết thúc dưới 2 phút.

Kiểm tra

Đây là mã hoàn chỉnh để kiểm tra nó:

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"
    }
}

Đầu ra trên máy của tôi:

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

Thật thú vị, điều này mất 51 giây mỗi lần chạy trên hộp E5-2699 v4 của tôi, nhưng chỉ 0,7 giây trên máy tính xách tay i5-5200U của tôi. Nó đạt được mức độ không điều kiện cần thiết trên máy tính xách tay trong khi đến dưới 5 giây tối đa, vì vậy nó vượt qua. Rõ ràng, bộ lập lịch của PowerShell không chơi tốt với nhiều lõi và các tác vụ ngắn.
Techrocket9

Và phải mất 58 giây trên i7 5960x
Techrocket9

Hừm ... 74 giây trên máy tính xách tay i5-6300U. Có thể đó là sự cố với Windows 10 hoặc PowerShell 5.1, vì i5-5200U là máy duy nhất trong số những máy được thử nghiệm không chạy Win10 (chạy 8.1).
Techrocket9

@ Techrocket9 kỳ lạ, tôi đã thử nghiệm trên Win10, PS 5.1. Trong ISE mặc dù.
nghĩa quân phiệt

2

GCC trên Linux, 47 byte

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

Điều này mang lại cho tôi các kết quả khác nhau khá nhiều lần, được biên dịch với gcc(không có cờ) phiên bản 4.9.2. Cụ thể, tôi đã sử dụng Debian 8.6-bit 64-bit (phiên bản kernel 3.16.31).

Giải trình

Nếu fork()trả về 0 (tiến trình con), giá trị của iđược in và điều kiện vòng lặp là sai, vì printfsẽ trả về giá trị lớn hơn 0. Trong tiến trình cha, điều kiện vòng lặp chỉ là i--.


Giống như câu trả lời bash. Xác định trên windows, nhưng chuyển qua Linux (trong trường hợp này là Debian).
Techrocket9
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.