როგორ ხორციელდება Ruby-ში წინასწარი მრავალრიცხოვანობა?
sobes.tech AI
პასუხი AI-სგან
წმინდა Ruby (MRI, JRuby, TruffleRuby) არ აქვს რეალური გამწევი მრავალრეწველობა ერთ პროცესში კოდის პარალელურად შესრულებისთვის, რადგან Global Interpreter Lock (GIL)-ი საშუალებას აძლევს მხოლოდ ერთ თრედს Ruby კოდის შესრულებას ნებისმიერ დროს:
თუმცა, გამწევი მრავალრეწველობა Ruby-ში არსებობს შეტანილი ინტერფეისის დონეზე. როდესაც თრედი ახორციელებს ბლოკირებადი შეტანილ-გამოტანილ ოპერაციას (მაგალითად, ფაილის წაკითხვა, ქსელის მოთხოვნა), GIL-ი გათავისუფლდება, რაც საშუალებას აძლევს სხვა თრედს Ruby კოდის შესრულებას. ეს საშუალებას აძლევს მიაღწიოს პარალელიზმს შეტანილ-გამოტანილ ოპერაციებისთვის, მაგრამ არა CPU-ზედ მორგებულ ამოცანებისთვის:
არსებობს ალტერნატიული Ruby რეალიზაციები (მაგალითად, Rubinius), რომლებიც ცდილობდნენ რეალური გამწევი მრავალრეწველობის განხორციელებას GIL- გარეშე, მაგრამ ისინი არ მიიღეს ისეთი ფართო გავრცელება, როგორც MRI:
პარალელურად CPU-ზედ მორგებული ამოცანების შესასრულებლად Ruby-ში ჩვეულებრივ გამოიყენება:
- პროცესები (
fork) — თითოეულ პროცესს აქვს თავისი GIL, რაც საშუალებას აძლევს Ruby კოდის პარალელურად შესრულებას. მონაცემთა გაცვლა პროცესებს შორის მოითხოვს სპეციალურ მექანიზმებს (IPC). - გარე ბიბლიოთეკები და C გაფართოებები — C ენაზე განხორციელებული ოპერაციები შეიძლება შესრულდეს GIL-ის კონტროლიდან გარეთ, უზრუნველყოფს პარალელურ შესრულებას:
Ruby 3.0-ში შემოვიდა Fibers Scheduler, რომელიც საშუალებას აძლევს ასინქრონულად შეასრულოს შეტანილ-გამოტანილ ოპერაციები, გამოყენებით ფიბერებს და არაბლოკიან ზარებს. ეს აუმჯობესებს I/O-ზედ მორგებული ამოცანების შესრულებას, მაგრამ არ აქცევს CPU-ზედ მორგებულ ამოცანებს რეალურად პარალელურ ერთ პროცესში:
# მაგალითი MRI-ის თრედების გამოყენებით I/O-ზედ მორგებული ამოცანებისთვის
require 'net/http'
require 'uri'
urls = %w[http://example.com http://ruby-lang.org]
threads = urls.map do |url|
Thread.new do
uri = URI.parse(url)
response = Net::HTTP.get_response(uri)
puts "ჩამოტვირთული #{url} (სტატუსი: #{response.code})"
end
end
threads.each(&:join)
ამგვარად, მიუხედავად იმისა, რომ Ruby-ს აქვს საშუალებები თრედებთან მუშაობისთვის, რეალური გამწევი მრავალრეწველობა CPU-ზედ მორგებულ ამოცანებზე ძირითადად მიღწეულია რამდენიმე პროცესის ან სპეციალური GIL-გაუქმებული Ruby რეალიზაციების გამოყენებით।