parallel 1.22.1 → 1.27.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/parallel/version.rb +1 -1
- data/lib/parallel.rb +110 -14
- metadata +6 -11
- data/lib/parallel/processor_count.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a657608c1d396b6c563f8905778d64d24c4ae6bb010e716e60a45ccc4a71295e
|
4
|
+
data.tar.gz: eb26d89f92521fed38f1bdf99f6374a2cca2e3f4c1557a7f3f92ed81d396ffb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d7accf7f9b3d74e1e76f7b89db8f9040d23876e8373a6d6fa9b31e927b9ca4ce8b13330ffd888871795c79d6e3bbe7b17aa787789146ffed67f46c21fa9af3ad
|
7
|
+
data.tar.gz: ead77e379ad1c18641ca8d0457214af393beeee60fe4e5558c69d601f6f269628ce2830b6a35a7fe66e461b88fbebad33dd9bb8b767324030294e2a8f7164d8d
|
data/lib/parallel/version.rb
CHANGED
data/lib/parallel.rb
CHANGED
@@ -1,11 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require 'rbconfig'
|
3
3
|
require 'parallel/version'
|
4
|
-
require 'parallel/processor_count'
|
5
4
|
|
6
5
|
module Parallel
|
7
|
-
extend ProcessorCount
|
8
|
-
|
9
6
|
Stop = Object.new.freeze
|
10
7
|
|
11
8
|
class DeadWorker < StandardError
|
@@ -27,7 +24,7 @@ module Parallel
|
|
27
24
|
attr_reader :backtrace
|
28
25
|
|
29
26
|
def initialize(original)
|
30
|
-
super
|
27
|
+
super("#{original.class}: #{original.message}")
|
31
28
|
@backtrace = original.backtrace
|
32
29
|
end
|
33
30
|
end
|
@@ -258,7 +255,7 @@ module Parallel
|
|
258
255
|
|
259
256
|
if options[:in_processes] && options[:in_threads]
|
260
257
|
raise ArgumentError, "Please specify only one of `in_processes` or `in_threads`."
|
261
|
-
elsif RUBY_PLATFORM =~ (/java/) && !
|
258
|
+
elsif RUBY_PLATFORM =~ (/java/) && !options[:in_processes]
|
262
259
|
method = :in_threads
|
263
260
|
size = options[method] || processor_count
|
264
261
|
elsif options[:in_threads]
|
@@ -303,8 +300,47 @@ module Parallel
|
|
303
300
|
map(array, options.merge(with_index: true), &block)
|
304
301
|
end
|
305
302
|
|
306
|
-
def flat_map(
|
307
|
-
map(
|
303
|
+
def flat_map(...)
|
304
|
+
map(...).flatten(1)
|
305
|
+
end
|
306
|
+
|
307
|
+
def filter_map(...)
|
308
|
+
map(...).compact
|
309
|
+
end
|
310
|
+
|
311
|
+
# Number of physical processor cores on the current system.
|
312
|
+
def physical_processor_count
|
313
|
+
@physical_processor_count ||= begin
|
314
|
+
ppc =
|
315
|
+
case RbConfig::CONFIG["target_os"]
|
316
|
+
when /darwin[12]/
|
317
|
+
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
|
318
|
+
when /linux/
|
319
|
+
cores = {} # unique physical ID / core ID combinations
|
320
|
+
phy = 0
|
321
|
+
File.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
|
322
|
+
if ln.start_with?("physical")
|
323
|
+
phy = ln[/\d+/]
|
324
|
+
elsif ln.start_with?("core")
|
325
|
+
cid = "#{phy}:#{ln[/\d+/]}"
|
326
|
+
cores[cid] = true unless cores[cid]
|
327
|
+
end
|
328
|
+
end
|
329
|
+
cores.count
|
330
|
+
when /mswin|mingw/
|
331
|
+
physical_processor_count_windows
|
332
|
+
else
|
333
|
+
processor_count
|
334
|
+
end
|
335
|
+
# fall back to logical count if physical info is invalid
|
336
|
+
ppc > 0 ? ppc : processor_count
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
# Number of processors seen by the OS or value considering CPU quota if the process is inside a cgroup,
|
341
|
+
# used for process scheduling
|
342
|
+
def processor_count
|
343
|
+
@processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || available_processor_count)
|
308
344
|
end
|
309
345
|
|
310
346
|
def worker_number
|
@@ -318,8 +354,35 @@ module Parallel
|
|
318
354
|
|
319
355
|
private
|
320
356
|
|
357
|
+
def physical_processor_count_windows
|
358
|
+
# Get-CimInstance introduced in PowerShell 3 or earlier: https://learn.microsoft.com/en-us/previous-versions/powershell/module/cimcmdlets/get-ciminstance?view=powershell-3.0
|
359
|
+
result = run(
|
360
|
+
'powershell -command "Get-CimInstance -ClassName Win32_Processor -Property NumberOfCores ' \
|
361
|
+
'| Select-Object -Property NumberOfCores"'
|
362
|
+
)
|
363
|
+
if !result || $?.exitstatus != 0
|
364
|
+
# fallback to deprecated wmic for older systems
|
365
|
+
result = run("wmic cpu get NumberOfCores")
|
366
|
+
end
|
367
|
+
if !result || $?.exitstatus != 0
|
368
|
+
# Bail out if both commands returned something unexpected
|
369
|
+
warn "guessing pyhsical processor count"
|
370
|
+
processor_count
|
371
|
+
else
|
372
|
+
# powershell: "\nNumberOfCores\n-------------\n 4\n\n\n"
|
373
|
+
# wmic: "NumberOfCores \n\n4 \n\n\n\n"
|
374
|
+
result.scan(/\d+/).map(&:to_i).reduce(:+)
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
def run(command)
|
379
|
+
IO.popen(command, &:read)
|
380
|
+
rescue Errno::ENOENT
|
381
|
+
# Ignore
|
382
|
+
end
|
383
|
+
|
321
384
|
def add_progress_bar!(job_factory, options)
|
322
|
-
if progress_options = options[:progress]
|
385
|
+
if (progress_options = options[:progress])
|
323
386
|
raise "Progressbar can only be used with array like items" if job_factory.size == Float::INFINITY
|
324
387
|
require 'ruby-progressbar'
|
325
388
|
|
@@ -348,7 +411,7 @@ module Parallel
|
|
348
411
|
results = []
|
349
412
|
exception = nil
|
350
413
|
begin
|
351
|
-
while set = job_factory.next
|
414
|
+
while (set = job_factory.next)
|
352
415
|
item, index = set
|
353
416
|
results << with_instrumentation(item, index, options) do
|
354
417
|
call_with_index(item, index, options, &block)
|
@@ -371,7 +434,7 @@ module Parallel
|
|
371
434
|
in_threads(options) do |worker_num|
|
372
435
|
self.worker_number = worker_num
|
373
436
|
# as long as there are more jobs, work on one of them
|
374
|
-
while !exception && set = job_factory.next
|
437
|
+
while !exception && (set = job_factory.next)
|
375
438
|
begin
|
376
439
|
item, index = set
|
377
440
|
result = with_instrumentation item, index, options do
|
@@ -415,7 +478,7 @@ module Parallel
|
|
415
478
|
|
416
479
|
# start
|
417
480
|
ractors.dup.each do |ractor|
|
418
|
-
if set = job_factory.next
|
481
|
+
if (set = job_factory.next)
|
419
482
|
item, index = set
|
420
483
|
instrument_start item, index, options
|
421
484
|
ractor.send [callback, item, index]
|
@@ -426,7 +489,7 @@ module Parallel
|
|
426
489
|
end
|
427
490
|
|
428
491
|
# replace with new items
|
429
|
-
while set = job_factory.next
|
492
|
+
while (set = job_factory.next)
|
430
493
|
item_next, index_next = set
|
431
494
|
done, (exception, result, item, index) = Ractor.select(*ractors)
|
432
495
|
if exception
|
@@ -600,13 +663,46 @@ module Parallel
|
|
600
663
|
end
|
601
664
|
|
602
665
|
def instrument_finish(item, index, result, options)
|
603
|
-
return unless on_finish = options[:finish]
|
666
|
+
return unless (on_finish = options[:finish])
|
667
|
+
return instrument_finish_in_order(item, index, result, options) if options[:finish_in_order]
|
604
668
|
options[:mutex].synchronize { on_finish.call(item, index, result) }
|
605
669
|
end
|
606
670
|
|
671
|
+
# yield results in the order of the input items
|
672
|
+
# needs to use `options` to store state between executions
|
673
|
+
# needs to use `done` index since a nil result would also be valid
|
674
|
+
def instrument_finish_in_order(item, index, result, options)
|
675
|
+
options[:mutex].synchronize do
|
676
|
+
# initialize our state
|
677
|
+
options[:finish_done] ||= []
|
678
|
+
options[:finish_expecting] ||= 0 # we wait for item at index 0
|
679
|
+
|
680
|
+
# store current result
|
681
|
+
options[:finish_done][index] = [item, result]
|
682
|
+
|
683
|
+
# yield all results that are now in order
|
684
|
+
break unless index == options[:finish_expecting]
|
685
|
+
index.upto(options[:finish_done].size).each do |i|
|
686
|
+
break unless (done = options[:finish_done][i])
|
687
|
+
options[:finish_done][i] = nil # allow GC to free this item and result
|
688
|
+
options[:finish].call(done[0], i, done[1])
|
689
|
+
options[:finish_expecting] += 1
|
690
|
+
end
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
607
694
|
def instrument_start(item, index, options)
|
608
|
-
return unless on_start = options[:start]
|
695
|
+
return unless (on_start = options[:start])
|
609
696
|
options[:mutex].synchronize { on_start.call(item, index) }
|
610
697
|
end
|
698
|
+
|
699
|
+
def available_processor_count
|
700
|
+
gem 'concurrent-ruby', '>= 1.3.4'
|
701
|
+
require 'concurrent-ruby'
|
702
|
+
Concurrent.available_processor_count.floor
|
703
|
+
rescue LoadError
|
704
|
+
require 'etc'
|
705
|
+
Etc.nprocessors
|
706
|
+
end
|
611
707
|
end
|
612
708
|
end
|
metadata
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.27.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
|
-
autorequire:
|
9
8
|
bindir: bin
|
10
9
|
cert_chain: []
|
11
|
-
date:
|
10
|
+
date: 2025-04-14 00:00:00.000000000 Z
|
12
11
|
dependencies: []
|
13
|
-
description:
|
14
12
|
email: michael@grosser.it
|
15
13
|
executables: []
|
16
14
|
extensions: []
|
@@ -18,17 +16,15 @@ extra_rdoc_files: []
|
|
18
16
|
files:
|
19
17
|
- MIT-LICENSE.txt
|
20
18
|
- lib/parallel.rb
|
21
|
-
- lib/parallel/processor_count.rb
|
22
19
|
- lib/parallel/version.rb
|
23
20
|
homepage: https://github.com/grosser/parallel
|
24
21
|
licenses:
|
25
22
|
- MIT
|
26
23
|
metadata:
|
27
24
|
bug_tracker_uri: https://github.com/grosser/parallel/issues
|
28
|
-
documentation_uri: https://github.com/grosser/parallel/blob/v1.
|
29
|
-
source_code_uri: https://github.com/grosser/parallel/tree/v1.
|
25
|
+
documentation_uri: https://github.com/grosser/parallel/blob/v1.27.0/Readme.md
|
26
|
+
source_code_uri: https://github.com/grosser/parallel/tree/v1.27.0
|
30
27
|
wiki_uri: https://github.com/grosser/parallel/wiki
|
31
|
-
post_install_message:
|
32
28
|
rdoc_options: []
|
33
29
|
require_paths:
|
34
30
|
- lib
|
@@ -36,15 +32,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
36
32
|
requirements:
|
37
33
|
- - ">="
|
38
34
|
- !ruby/object:Gem::Version
|
39
|
-
version: '2.
|
35
|
+
version: '2.7'
|
40
36
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
37
|
requirements:
|
42
38
|
- - ">="
|
43
39
|
- !ruby/object:Gem::Version
|
44
40
|
version: '0'
|
45
41
|
requirements: []
|
46
|
-
rubygems_version: 3.
|
47
|
-
signing_key:
|
42
|
+
rubygems_version: 3.6.2
|
48
43
|
specification_version: 4
|
49
44
|
summary: Run any kind of code in parallel processes
|
50
45
|
test_files: []
|
@@ -1,44 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module Parallel
|
3
|
-
# TODO: inline this method into parallel.rb and kill physical_processor_count in next major release
|
4
|
-
module ProcessorCount
|
5
|
-
# Number of processors seen by the OS, used for process scheduling
|
6
|
-
def processor_count
|
7
|
-
require 'etc'
|
8
|
-
@processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || Etc.nprocessors)
|
9
|
-
end
|
10
|
-
|
11
|
-
# Number of physical processor cores on the current system.
|
12
|
-
def physical_processor_count
|
13
|
-
@physical_processor_count ||= begin
|
14
|
-
ppc =
|
15
|
-
case RbConfig::CONFIG["target_os"]
|
16
|
-
when /darwin[12]/
|
17
|
-
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
|
18
|
-
when /linux/
|
19
|
-
cores = {} # unique physical ID / core ID combinations
|
20
|
-
phy = 0
|
21
|
-
File.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
|
22
|
-
if ln.start_with?("physical")
|
23
|
-
phy = ln[/\d+/]
|
24
|
-
elsif ln.start_with?("core")
|
25
|
-
cid = "#{phy}:#{ln[/\d+/]}"
|
26
|
-
cores[cid] = true unless cores[cid]
|
27
|
-
end
|
28
|
-
end
|
29
|
-
cores.count
|
30
|
-
when /mswin|mingw/
|
31
|
-
require 'win32ole'
|
32
|
-
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
|
33
|
-
"select NumberOfCores from Win32_Processor"
|
34
|
-
)
|
35
|
-
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
|
36
|
-
else
|
37
|
-
processor_count
|
38
|
-
end
|
39
|
-
# fall back to logical count if physical info is invalid
|
40
|
-
ppc > 0 ? ppc : processor_count
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|