[ACCEPTED]-Detect number of CPUs installed-ruby
As of Ruby version 2.2.3, the etc
module in 8 Ruby's stdlib offers an nprocessors
method which returns 7 the number of processors. The caveat to 6 this, is that if ruby is relegated to a 5 subset of CPU cores, Etc.nprocessors
will only return the 4 number of cores that Ruby has access to. Also, as 3 seanlinsley pointed out, this will only return virtual 2 cores instead of physical cores, which may 1 result in a disparity in the expected value.
require 'etc'
p Etc.nprocessors #=> 4
EDIT: Now rails ships with concurrent-ruby 9 as a dependency so it's probably the best 8 solution;
$ gem install concurrent-ruby
$ irb
irb(main):001:0> require 'concurrent'
=> true
irb(main):002:0> Concurrent.processor_count
=> 8
irb(main):003:0> Concurrent.physical_processor_count
=> 4
see http://ruby-concurrency.github.io/concurrent-ruby/master/Concurrent.html for more info. Because it 7 does both physical and logical cores, it's 6 better than the inbuilt Etc.nprocessors
.
and here is the 5 previous answer;
$ gem install facter
$ irb
irb(main):001:0> require 'facter'
=> true
irb(main):002:0> puts Facter.value('processors')['count']
4
=> nil
irb(main):003:0>
This facter gem is the best if you 4 want other facts about the system too, it's 3 not platform specific and designed to do 2 this exact thing.
UPDATE: updated to include 1 Nathan Kleyn's tip on the api change.
I am currently using this, which covers 1 all os. https://github.com/grosser/parallel/blob/master/lib/parallel.rb#L63
def self.processor_count
case RbConfig::CONFIG['host_os']
when /darwin9/
`hwprefs cpu_count`.to_i
when /darwin/
((`which hwprefs` != '') ? `hwprefs thread_count` : `sysctl -n hw.ncpu`).to_i
when /linux/
`cat /proc/cpuinfo | grep processor | wc -l`.to_i
when /freebsd/
`sysctl -n hw.ncpu`.to_i
when /mswin|mingw/
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
cpu = wmi.ExecQuery("select NumberOfCores from Win32_Processor") # TODO count hyper-threaded in this
cpu.to_enum.first.NumberOfCores
end
end
with JRuby you can check it with the following 1 Java code:
Runtime runtime = Runtime.getRuntime();
int numberOfProcessors = runtime.availableProcessors();
Here is an implementation for Linux, OSX, Windows 1 and BSD: https://gist.github.com/1009994
Source code:
module System
extend self
def cpu_count
return Java::Java.lang.Runtime.getRuntime.availableProcessors if defined? Java::Java
return File.read('/proc/cpuinfo').scan(/^processor\s*:/).size if File.exist? '/proc/cpuinfo'
require 'win32ole'
WIN32OLE.connect("winmgmts://").ExecQuery("select * from Win32_ComputerSystem").NumberOfProcessors
rescue LoadError
Integer `sysctl -n hw.ncpu 2>/dev/null` rescue 1
end
end
System.cpu_count # => 2
Surely if you can cat
it, you can open, read 5 and close it using the standard features 4 of the language without resorting to a system()
-type 3 call.
You may just need to detect what platform 2 you're on dynamically and either:
- use the
/proc/cpuinfo
"file" for Linux; or - communicate with WMI for Windows.
That last 1 line can use:
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
info = wmi.ExecQuery ("select * from Win32_ComputerSystem")
Then use info's NumberOfProcessors item.
I tried using Facter
but found it a bit slow. I 2 tried system
gem and found it a lot faster. It 1 is also very easy to use: System::CPU.count
.
In linux you can also use nproc
, which is cleaner 4 that the other subshell-based solutions 3 here. I wanted vagrant to give the same 2 number of CPUs to the virtual machine as 1 the host has. I added this to Vagrantfile
:
vb.cpus = `nproc`.to_i
on Mac:
thiago-pradis-macbook:~ tchandy$ hwprefs 1 cpu_count
2
@grosser:
when /linux/ `grep -c processor /proc/cpuinfo`.to_i
http://www.partmaps.org/era/unix/award.html#cat
http://www.partmaps.org/era/unix/award.html#wc
0
I found something recently that may have 22 to be taken into consideration. You can 21 deactivate processors (take them offline), and 20 then facter processorcount (plus some of 19 the other methods above) gives the wrong 18 result. You can count processor lines in 17 /proc/cpuinfo, as long as you do it correctly. If 16 you just populate an array with index numbers 15 of the procs, if you have gaps in the procs 14 (as in, procs 0,1,2,10,11,12 are active, all 13 others to 20 say are inactive), it will 12 automatically spring indexes 3-9 into existence 11 (sort of), at least Array#size will report 10 13 in that case. You would have to do #compact 9 to get the number of active processors. However, if 8 you want total processors, perhaps better 7 is looking at /sys/devices/system/cpu[0-9], and 6 count that up. That will give you the total 5 number of processors, but not how many (or 4 which ones) are active.
Just something to 3 think about. I trying to put through a 2 patch to facter to add an activeprocessorcount 1 and totalprocessorcount fact.
Combination of @grosser's and @paxdiablo's 6 answer, since on my system (winxp) win32_computersystem 5 doesn't have any processor info; this works 4 though:
require 'win32ole'
wmi = WIN32OLE.connect("winmgmts://")
info = wmi.ExecQuery ("select NumberOfCores from Win32_processor")
puts info.to_enum.first.NumberOfCores
To see what's available on your system, run 3 this from powershell (i used 1.0 in this case):
Get-WmiObject -list
(might 2 want to pipe to grep if you've got cygwin 1 installed)
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.