patternpythonMinor
Checking for hyperthreading
Viewed 0 times
checkinghyperthreadingfor
Problem
I want to just write a simple function to check if my linux box has hyperthreading enabled. I want to know if there's a simpler way to produce the
cpuinfo dict (would be great if I could use a dict comprehension somehow) or generally a better way to check this information:def is_hyperthreading_enabled():
cpuinfo = dict(map(str.strip, line.split(':'))
for line in open('/proc/cpuinfo')
if ':' in line)
return cpuinfo['siblings'] != cpuinfo['cpu cores']Solution
First off, you should always
There are two ways to do that.
-
The old style way:
file_handler = open('/proc/cpuinfo')
// Your code here
file_handler.close()
-
The 'new' way with
with open('/proc/cpuinfo') as file_handler:
// Your code here
The second is more recommended as then it's both clear when the file is open, and you don't forget to close it.
While
To avoid this as an issue, you can use the optional second argument to
If you want to use a dictionary comprehension at all cost. Then it's the same as your above code, but it will have a dictionary comprehension surrounding it.
This is in my opinion worse than your above code, as it's common knowledge that
And your original code is a lot less verbose.
You could however use a functional approach to this. Which has the drawback of needing to define
Overall I would recommend using your original code, but with
Just to note,
For example from my
This also shows that the information can change. E.g.
Due to this I would recommend that you change your function to make
Finally as far as I know unless you read the entire file and split on
And so I would recommend:
Note, the above works as I make the assumption that the file always ends with an empty line. Otherwise you would be missing one of the cores. This assumption seems to be true, as I tested if
If you think this is too small a test case, you can add the following after the for loop.
So if you only care about one core, your way is best. If you want to test if any CPU can, then you would want to use the above. And if you want to know if all of them can then you should change
close a file in Python.There are two ways to do that.
-
The old style way:
file_handler = open('/proc/cpuinfo')
// Your code here
file_handler.close()
-
The 'new' way with
with.with open('/proc/cpuinfo') as file_handler:
// Your code here
The second is more recommended as then it's both clear when the file is open, and you don't forget to close it.
While
/proc/cpuinfo is unlikely to have more than one : per line, it could happen. As it seems model name can be whatever the model is called. If a vendor were to put a : in their name, your code won't work. with the exception:ValueError: dictionary update sequence element #1 has length 3; 2 is requiredTo avoid this as an issue, you can use the optional second argument to
str.split(':', 1).If you want to use a dictionary comprehension at all cost. Then it's the same as your above code, but it will have a dictionary comprehension surrounding it.
with open('/proc/cpuinfo') as file_handler:
cpuinfo = {
key: value
for key, value in (
map(str.strip, line.split(':', 1))
for line in file_handler
if ':' in line
)
}This is in my opinion worse than your above code, as it's common knowledge that
dict([['key', 'value']]) can be used to make a dict, which was added in 2.2. Where dictionary comprehensions were added in 2.7.And your original code is a lot less verbose.
You could however use a functional approach to this. Which has the drawback of needing to define
line twice, and is more verbose than the original code.with open('/proc/cpuinfo') as file_handler:
cpuinfo = dict(map(
lambda line: map(str.strip, line.split(':', 1)),
filter(lambda line: ':' in line, file_handler)
))Overall I would recommend using your original code, but with
with and line.split(':', 1)) added.Just to note,
':' in line returns false every time the CPU core changes.For example from my
/proc/info. (note I removed the flags)processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz
stepping : 7
microcode : 0x28
cpu MHz : 1728.761
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
bugs :
bogomips : 6800.31
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz
stepping : 7
microcode : 0x28
cpu MHz : 1686.609
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 1
cpu cores : 4
apicid : 2
initial apicid : 2
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
bugs :
bogomips : 6800.31
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:This also shows that the information can change. E.g.
cpu MHz:1728.761 and cpu MHz:1686.609. So you may not want to overwrite some of this information. Also if you have more than one CPU (say you are using a sever) then you could return false on one CPU and true on another, but as the last core overwrites all the previous data it's somewhat up to chance to know.Due to this I would recommend that you change your function to make
cpuinfo a list of dicts.Finally as far as I know unless you read the entire file and split on
\n\n then there is no way to make it a comprehension.And so I would recommend:
def is_hyperthreading_enabled():
with open('/proc/cpuinfo') as file_handler:
cpuinfo = []
temp_dict = {}
for line in file_handler:
try:
key, value = map(str.strip, line.split(':', 1))
except ValueError:
cpuinfo.append(temp_dict)
temp_dict = {}
else:
temp_dict[key] = value
return any(map(lambda core: core['siblings'] != core['cpu cores'], cpuinfo))Note, the above works as I make the assumption that the file always ends with an empty line. Otherwise you would be missing one of the cores. This assumption seems to be true, as I tested if
/proc/cpuinfo ends with an empty line on all a single; quad-core, dual-core and single core, CPU.If you think this is too small a test case, you can add the following after the for loop.
if temp_dict:
cpuinfo.append(temp_dict)So if you only care about one core, your way is best. If you want to test if any CPU can, then you would want to use the above. And if you want to know if all of them can then you should change
any to all in the above.Code Snippets
ValueError: dictionary update sequence element #1 has length 3; 2 is requiredwith open('/proc/cpuinfo') as file_handler:
cpuinfo = {
key: value
for key, value in (
map(str.strip, line.split(':', 1))
for line in file_handler
if ':' in line
)
}with open('/proc/cpuinfo') as file_handler:
cpuinfo = dict(map(
lambda line: map(str.strip, line.split(':', 1)),
filter(lambda line: ':' in line, file_handler)
))processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz
stepping : 7
microcode : 0x28
cpu MHz : 1728.761
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
bugs :
bogomips : 6800.31
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 42
model name : Intel(R) Core(TM) i5-2500 CPU @ 3.30GHz
stepping : 7
microcode : 0x28
cpu MHz : 1686.609
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 1
cpu cores : 4
apicid : 2
initial apicid : 2
fpu : yes
fpu_exception : yes
cpuid level : 13
wp : yes
bugs :
bogomips : 6800.31
clflush size : 64
cache_alignment : 64
address sizes : 36 bits physical, 48 bits virtual
power management:def is_hyperthreading_enabled():
with open('/proc/cpuinfo') as file_handler:
cpuinfo = []
temp_dict = {}
for line in file_handler:
try:
key, value = map(str.strip, line.split(':', 1))
except ValueError:
cpuinfo.append(temp_dict)
temp_dict = {}
else:
temp_dict[key] = value
return any(map(lambda core: core['siblings'] != core['cpu cores'], cpuinfo))Context
StackExchange Code Review Q#109305, answer score: 4
Revisions (0)
No revisions yet.