Enze Chi
Enze Chi

Reputation: 1763

How to find the number of CPUs in tcl?

The software I am using support multiple thread and TCL interface. So I am not sure how to find the number of CPUs in TCL to limit the maximum threads.

Upvotes: 2

Views: 2204

Answers (3)

linucks
linucks

Reputation: 815

I tried both the solutions above. @DonalFellows was almost perfect but didn't work on my OSX as the default tclsh was 8.4 and the {*} syntax to exec didn't work. However the {*} construct didn't seem to be required as removing it enabled it to work with tclsh 8.4, 8.5 and 8.6.

I've pasted the code below with that change as I don't have enough reputation to just comment.

proc numberOfCPUs {} {
    # Windows puts it in an environment variable
    global tcl_platform env
    if {$tcl_platform(platform) eq "windows"} {
        return $env(NUMBER_OF_PROCESSORS)
    }

    # Check for sysctl (OSX, BSD)
    set sysctl [auto_execok "sysctl"]
    if {[llength $sysctl]} {
        if {![catch {exec $sysctl -n "hw.ncpu"} cores]} {
            return $cores
        }
    }

    # Assume Linux, which has /proc/cpuinfo, but be careful
    if {![catch {open "/proc/cpuinfo"} f]} {
        set cores [regexp -all -line {^processor\s} [read $f]]
        close $f
        if {$cores > 0} {
            return $cores
        }
    }

    # No idea what the actual number of cores is; exhausted all our options
    # Fall back to returning 1; there must be at least that because we're running on it!
    return 1
}

Upvotes: 1

Enze Chi
Enze Chi

Reputation: 1763

The code originally comes from @DonalFellows's answer. But I still get problem with the sysctl which exists in Ubuntu but it doesn't have hw.ncpu.

So I did some changes on it.

proc number_of_processor {} {
    global tcl_platform env
    switch ${tcl_platform(platform)} {
        "windows" { 
            return $env(NUMBER_OF_PROCESSORS)       
        }

        "unix" {
            if {![catch {open "/proc/cpuinfo"} f]} {
                set cores [regexp -all -line {^processor\s} [read $f]]
                close $f
                if {$cores > 0} {
                    return $cores
                }
            }
        }

        "Darwin" {
            if {![catch {exec {*}$sysctl -n "hw.ncpu"} cores]} {
                return $cores
            }
        }

        default {
            puts "Unknown System"
            return 1
        }
    }
}

Tried on Ubuntu and Windows 7, it works. I don't have MacOS around me. So that will be good if someone can verify that works or not.

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137567

There's nothing built into Tcl; it's been discussed, but not acted on because the number of CPUs is not necessarily the number that the process may use (by far the most relevant reason for having the info). That said, the information is available. It's just that the way you get the information varies by platform.

proc numberOfCPUs {} {
    # Windows puts it in an environment variable
    global tcl_platform env
    if {$tcl_platform(platform) eq "windows"} {
        return $env(NUMBER_OF_PROCESSORS)
    }

    # Check for sysctl (OSX, BSD)
    set sysctl [auto_execok "sysctl"]
    if {[llength $sysctl]} {
        if {![catch {exec {*}$sysctl -n "hw.ncpu"} cores]} {
            return $cores
        }
    }

    # Assume Linux, which has /proc/cpuinfo, but be careful
    if {![catch {open "/proc/cpuinfo"} f]} {
        set cores [regexp -all -line {^processor\s} [read $f]]
        close $f
        if {$cores > 0} {
            return $cores
        }
    }

    # No idea what the actual number of cores is; exhausted all our options
    # Fall back to returning 1; there must be at least that because we're running on it!
    return 1
}

Note that if you're looking to find out the number of CPUs to run on, what you really want are the number of bits set in the CPU affinity mask. Unfortunately, retrieving that information is non-trivial on most platforms.

Upvotes: 4

Related Questions