[ACCEPTED]-Detect number of CPUs installed-ruby

Accepted answer
Score: 48

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
Score: 43

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.

Score: 27

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
Score: 11

with JRuby you can check it with the following 1 Java code:

 Runtime runtime = Runtime.getRuntime();   
 int numberOfProcessors = runtime.availableProcessors(); 
Score: 11

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
Score: 5

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.

Score: 3

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.

Score: 3

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
Score: 1

on Mac:

thiago-pradis-macbook:~ tchandy$ hwprefs 1 cpu_count

2

Score: 1

@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

Score: 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.

Score: 0

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