[Numpy-svn] r4152 - trunk/numpy/distutils

numpy-svn@scip... numpy-svn@scip...
Tue Oct 2 14:14:54 CDT 2007


Author: cookedm
Date: 2007-10-02 14:14:52 -0500 (Tue, 02 Oct 2007)
New Revision: 4152

Modified:
   trunk/numpy/distutils/cpuinfo.py
Log:
Update distutils/cpuinfo.py
 * convert class names to CamelCase
 * Add PentiumM to LinuxCPUInfo and Win32CPUInfo. Also add it to SSE2 detection.
 * remove is_Athlon64() and is_Operton() from Win32CPUInfo, and add
   is_AMD64(). We can't reliably distinguish between the two (or from
   other 64-bit Athlons). Also add is_AMD64() to LinuxCPUInfo.
 * Factor out common command output checking, and remove (most) of the
   bare try/excepts used in the __init__ methods (exception is
   Win32CPUInfo; don't know what exceptions could be thrown). Use
   warnings.warn instead of printing exceptions to stderr


Modified: trunk/numpy/distutils/cpuinfo.py
===================================================================
--- trunk/numpy/distutils/cpuinfo.py	2007-10-02 07:54:11 UTC (rev 4151)
+++ trunk/numpy/distutils/cpuinfo.py	2007-10-02 19:14:52 UTC (rev 4152)
@@ -8,23 +8,55 @@
 terms of the NumPy (BSD style) license.  See LICENSE.txt that came with
 this distribution for specifics.
 
-Note:  This should be merged into proc at some point.  Perhaps proc should
-be returning classes like this instead of using dictionaries.
-
 NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
-$Revision: 1.1 $
-$Date: 2005/04/09 19:29:34 $
 Pearu Peterson
 """
 
-__version__ = "$Id: cpuinfo.py,v 1.1 2005/04/09 19:29:34 pearu Exp $"
-
 __all__ = ['cpu']
 
 import sys, re, types
+import os
 import commands
+import warnings
 
-class cpuinfo_base(object):
+def getoutput(cmd, successful_status=(0,), stacklevel=1):
+    try:
+        status, output = commands.getstatusoutput(cmd)
+    except EnvironmentError, e:
+        warnings.warn(str(e), UserWarning, stacklevel=stacklevel)
+        return False, output
+    if os.WIFEXITED(status) and os.WEXITSTATUS(status) in successful_status:
+        return True, output
+    return False, output
+
+def command_info(successful_status=(0,), stacklevel=1, **kw):
+    info = {}
+    for key in kw:
+        ok, output = getoutput(kw[key], successful_status=successful_status,
+                               stacklevel=stacklevel+1)
+        if ok:
+            info[key] = output.strip()
+    return info
+
+def command_by_line(cmd, successful_status=(0,), stacklevel=1):
+    ok, output = getoutput(cmd, successful_status=successful_status,
+                           stacklevel=stacklevel+1)
+    if not ok:
+        return
+    for line in output.splitlines():
+        yield line.strip()
+
+def key_value_from_command(cmd, sep, successful_status=(0,),
+                           stacklevel=1):
+    d = {}
+    for line in command_by_line(cmd, successful_status=successful_status,
+                                stacklevel=stacklevel+1):
+        l = [s.strip() for s in line.split(sep, 1)]
+        if len(l) == 2:
+            d[l[0]] = l[1]
+    return d
+
+class CPUInfoBase(object):
     """Holds CPU information and provides methods for requiring
     the availability of various CPU features.
     """
@@ -36,7 +68,7 @@
             pass
 
     def __getattr__(self,name):
-        if name[0]!='_':
+        if not name.startswith('_'):
             if hasattr(self,'_'+name):
                 attr = getattr(self,'_'+name)
                 if type(attr) is types.MethodType:
@@ -51,29 +83,31 @@
     def _is_32bit(self):
         return not self.is_64bit()
 
-class linux_cpuinfo(cpuinfo_base):
+class LinuxCPUInfo(CPUInfoBase):
 
     info = None
 
     def __init__(self):
         if self.info is not None:
             return
-        info = []
+        info = [ {} ]
+        ok, output = getoutput('uname -m')
+        if ok:
+            info[0]['uname_m'] = output.strip()
         try:
-            for line in open('/proc/cpuinfo').readlines():
+            fo = open('/proc/cpuinfo')
+        except EnvironmentError, e:
+            warnings.warn(str(e), UserWarning)
+        else:
+            for line in fo:
                 name_value = [s.strip() for s in line.split(':', 1)]
-                if len(name_value)!=2:
+                if len(name_value) != 2:
                     continue
-                name,value = name_value
+                name, value = name_value
                 if not info or info[-1].has_key(name): # next processor
                     info.append({})
                 info[-1][name] = value
-            status,output = commands.getstatusoutput('uname -m')
-            if not status:
-                if not info: info.append({})
-                info[-1]['uname_m'] = output.strip()
-        except:
-            print sys.exc_value,'(ignoring)'
+            fo.close()
         self.__class__.info = info
 
     def _not_impl(self): pass
@@ -99,6 +133,9 @@
         return re.match(r'.*?Athlon\(tm\) MP\b',
                         self.info[0]['model name']) is not None
 
+    def _is_AMD64(self):
+        return self.is_AMD() and self.info[0]['family'] == '15'
+
     def _is_Athlon64(self):
         return re.match(r'.*?Athlon\(tm\) 64\b',
                         self.info[0]['model name']) is not None
@@ -248,41 +285,26 @@
     def _is_32bit(self):
         return not self.is_64bit()
 
-class irix_cpuinfo(cpuinfo_base):
-
+class IRIXCPUInfo(CPUInfoBase):
     info = None
 
     def __init__(self):
         if self.info is not None:
             return
-        info = []
-        try:
-            status,output = commands.getstatusoutput('sysconf')
-            if status not in [0,256]:
-                return
-            for line in output.split('\n'):
-                name_value = [s.strip() for s in line.split(' ', 1)]
-                if len(name_value)!=2:
-                    continue
-                name,value = name_value
-                if not info:
-                    info.append({})
-                info[-1][name] = value
-        except:
-            print sys.exc_value,'(ignoring)'
+        info = key_value_from_command('sysconf', sep=' ',
+                                      successful_status=(0,1))
         self.__class__.info = info
 
-        #print info
     def _not_impl(self): pass
 
     def _is_singleCPU(self):
-        return self.info[0].get('NUM_PROCESSORS') == '1'
+        return self.info.get('NUM_PROCESSORS') == '1'
 
     def _getNCPUs(self):
-        return int(self.info[0].get('NUM_PROCESSORS'))
+        return int(self.info.get('NUM_PROCESSORS', 1))
 
     def __cputype(self,n):
-        return self.info[0].get('PROCESSORS').split()[0].lower() == 'r%s' % (n)
+        return self.info.get('PROCESSORS').split()[0].lower() == 'r%s' % (n)
     def _is_r2000(self): return self.__cputype(2000)
     def _is_r3000(self): return self.__cputype(3000)
     def _is_r3900(self): return self.__cputype(3900)
@@ -300,10 +322,10 @@
     def _is_rorion(self): return self.__cputype('orion')
 
     def get_ip(self):
-        try: return self.info[0].get('MACHINE')
+        try: return self.info.get('MACHINE')
         except: pass
     def __machine(self,n):
-        return self.info[0].get('MACHINE').lower() == 'ip%s' % (n)
+        return self.info.get('MACHINE').lower() == 'ip%s' % (n)
     def _is_IP19(self): return self.__machine(19)
     def _is_IP20(self): return self.__machine(20)
     def _is_IP21(self): return self.__machine(21)
@@ -320,52 +342,33 @@
     def _is_IP32_5k(self): return self.__machine(32) and self._is_r5000()
     def _is_IP32_10k(self): return self.__machine(32) and self._is_r10000()
 
-class darwin_cpuinfo(cpuinfo_base):
 
+class DarwinCPUInfo(CPUInfoBase):
     info = None
 
     def __init__(self):
         if self.info is not None:
             return
-        info = []
-        try:
-            status,output = commands.getstatusoutput('arch')
-            if not status:
-                if not info: info.append({})
-                info[-1]['arch'] = output.strip()
-            status,output = commands.getstatusoutput('machine')
-            if not status:
-                if not info: info.append({})
-                info[-1]['machine'] = output.strip()
-            status,output = commands.getstatusoutput('sysctl hw')
-            if not status:
-                if not info: info.append({})
-                d = {}
-                for l in output.splitlines():
-                    l = [s.strip() for s in l.split('=')]
-                    if len(l)==2:
-                        d[l[0]]=l[1]
-                info[-1]['sysctl_hw'] = d
-        except:
-            print sys.exc_value,'(ignoring)'
+        info = command_info(arch='arch',
+                            machine='machine')
+        info['sysctl_hw'] = key_value_from_command('sysctl hw', sep='=')
         self.__class__.info = info
 
     def _not_impl(self): pass
 
     def _getNCPUs(self):
-        try: return int(self.info[0]['sysctl_hw']['hw.ncpu'])
-        except: return 1
+        return int(self.info['sysctl_hw'].get('hw.ncpu', 1))
 
     def _is_Power_Macintosh(self):
-        return self.info[0]['sysctl_hw']['hw.machine']=='Power Macintosh'
+        return self.info['sysctl_hw']['hw.machine']=='Power Macintosh'
 
     def _is_i386(self):
-        return self.info[0]['arch']=='i386'
+        return self.info['arch']=='i386'
     def _is_ppc(self):
-        return self.info[0]['arch']=='ppc'
+        return self.info['arch']=='ppc'
 
     def __machine(self,n):
-        return self.info[0]['machine'] == 'ppc%s'%n
+        return self.info['machine'] == 'ppc%s'%n
     def _is_ppc601(self): return self.__machine(601)
     def _is_ppc602(self): return self.__machine(602)
     def _is_ppc603(self): return self.__machine(603)
@@ -385,124 +388,90 @@
     def _is_ppc823(self): return self.__machine(823)
     def _is_ppc860(self): return self.__machine(860)
 
-class sunos_cpuinfo(cpuinfo_base):
 
+class SunOSCPUInfo(CPUInfoBase):
+
     info = None
 
     def __init__(self):
         if self.info is not None:
             return
-        info = []
-        try:
-            status,output = commands.getstatusoutput('arch')
-            if not status:
-                if not info:
-                    info.append({})
-                info[-1]['arch'] = output.strip()
-            status,output = commands.getstatusoutput('mach')
-            if not status:
-                if not info:
-                    info.append({})
-                info[-1]['mach'] = output.strip()
-            status,output = commands.getstatusoutput('uname -i')
-            if not status:
-                if not info:
-                    info.append({})
-                info[-1]['uname_i'] = output.strip()
-            status,output = commands.getstatusoutput('uname -X')
-            if not status:
-                if not info: info.append({})
-                d = {}
-                for l in output.splitlines():
-                    l = [s.strip() for s in l.split('=')]
-                    if len(l)==2:
-                        d[l[0]]=l[1]
-                info[-1]['uname_X'] = d
-            status,output = commands.getstatusoutput('isainfo -b')
-            if not status:
-                if not info:
-                    info.append({})
-                info[-1]['isainfo_b'] = output.strip()
-            status,output = commands.getstatusoutput('isainfo -n')
-            if not status:
-                if not info:
-                    info.append({})
-                info[-1]['isainfo_n'] = output.strip()
-            status,output = commands.getstatusoutput('psrinfo -v 0')
-            if not status:
-                if not info: info.append({})
-                for l in output.splitlines():
-                    m = re.match(r'\s*The (?P<p>[\w\d]+) processor operates at',l)
-                    if m:
-                        info[-1]['processor'] = m.group('p')
-                        break
-        except:
-            print sys.exc_value,'(ignoring)'
+        info = command_info(arch='arch',
+                            mach='mach',
+                            uname_i='uname_i',
+                            isainfo_b='isainfo -b',
+                            isainfo_n='isainfo -n',
+                            )
+        info['uname_X'] = key_value_from_command('uname -X', sep='=')
+        for line in command_by_line('psrinfo -v 0'):
+            m = re.match(r'\s*The (?P<p>[\w\d]+) processor operates at', line)
+            if m:
+                info['processor'] = m.group('p')
+                break
         self.__class__.info = info
 
     def _not_impl(self): pass
 
     def _is_32bit(self):
-        return self.info[0]['isainfo_b']=='32'
+        return self.info['isainfo_b']=='32'
     def _is_64bit(self):
-        return self.info[0]['isainfo_b']=='64'
+        return self.info['isainfo_b']=='64'
 
     def _is_i386(self):
-        return self.info[0]['isainfo_n']=='i386'
+        return self.info['isainfo_n']=='i386'
     def _is_sparc(self):
-        return self.info[0]['isainfo_n']=='sparc'
+        return self.info['isainfo_n']=='sparc'
     def _is_sparcv9(self):
-        return self.info[0]['isainfo_n']=='sparcv9'
+        return self.info['isainfo_n']=='sparcv9'
 
     def _getNCPUs(self):
-        try: return int(self.info[0]['uname_X']['NumCPU'])
-        except: return 1
+        return int(self.info['uname_X'].get('NumCPU', 1))
 
     def _is_sun4(self):
-        return self.info[0]['arch']=='sun4'
+        return self.info['arch']=='sun4'
 
     def _is_SUNW(self):
-        return re.match(r'SUNW',self.info[0]['uname_i']) is not None
+        return re.match(r'SUNW',self.info['uname_i']) is not None
     def _is_sparcstation5(self):
-        return re.match(r'.*SPARCstation-5',self.info[0]['uname_i']) is not None
+        return re.match(r'.*SPARCstation-5',self.info['uname_i']) is not None
     def _is_ultra1(self):
-        return re.match(r'.*Ultra-1',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-1',self.info['uname_i']) is not None
     def _is_ultra250(self):
-        return re.match(r'.*Ultra-250',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-250',self.info['uname_i']) is not None
     def _is_ultra2(self):
-        return re.match(r'.*Ultra-2',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-2',self.info['uname_i']) is not None
     def _is_ultra30(self):
-        return re.match(r'.*Ultra-30',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-30',self.info['uname_i']) is not None
     def _is_ultra4(self):
-        return re.match(r'.*Ultra-4',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-4',self.info['uname_i']) is not None
     def _is_ultra5_10(self):
-        return re.match(r'.*Ultra-5_10',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-5_10',self.info['uname_i']) is not None
     def _is_ultra5(self):
-        return re.match(r'.*Ultra-5',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-5',self.info['uname_i']) is not None
     def _is_ultra60(self):
-        return re.match(r'.*Ultra-60',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-60',self.info['uname_i']) is not None
     def _is_ultra80(self):
-        return re.match(r'.*Ultra-80',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-80',self.info['uname_i']) is not None
     def _is_ultraenterprice(self):
-        return re.match(r'.*Ultra-Enterprise',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-Enterprise',self.info['uname_i']) is not None
     def _is_ultraenterprice10k(self):
-        return re.match(r'.*Ultra-Enterprise-10000',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra-Enterprise-10000',self.info['uname_i']) is not None
     def _is_sunfire(self):
-        return re.match(r'.*Sun-Fire',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Sun-Fire',self.info['uname_i']) is not None
     def _is_ultra(self):
-        return re.match(r'.*Ultra',self.info[0]['uname_i']) is not None
+        return re.match(r'.*Ultra',self.info['uname_i']) is not None
 
     def _is_cpusparcv7(self):
-        return self.info[0]['processor']=='sparcv7'
+        return self.info['processor']=='sparcv7'
     def _is_cpusparcv8(self):
-        return self.info[0]['processor']=='sparcv8'
+        return self.info['processor']=='sparcv8'
     def _is_cpusparcv9(self):
-        return self.info[0]['processor']=='sparcv9'
+        return self.info['processor']=='sparcv9'
 
-class win32_cpuinfo(cpuinfo_base):
+class Win32CPUInfo(CPUInfoBase):
 
     info = None
-    pkey = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor"
+    pkey = r"HARDWARE\DESCRIPTION\System\CentralProcessor"
     # XXX: what does the value of
     #   HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor\0
     # mean?
@@ -514,10 +483,9 @@
         try:
             #XXX: Bad style to use so long `try:...except:...`. Fix it!
             import _winreg
-            pkey = "HARDWARE\\DESCRIPTION\\System\\CentralProcessor"
             prgx = re.compile(r"family\s+(?P<FML>\d+)\s+model\s+(?P<MDL>\d+)"\
                               "\s+stepping\s+(?P<STP>\d+)",re.IGNORECASE)
-            chnd=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,pkey)
+            chnd=_winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, self.pkey)
             pnum=0
             while 1:
                 try:
@@ -576,16 +544,15 @@
         return self.is_AMD() and self.info[0]['Family']==5 \
                and self.info[0]['Model']==9
 
-    def _is_Athlon(self):
-        return self.is_AMD() and self.info[0]['Family']==6
+    def _is_AMDK7(self):
+        return self.is_AMD() and self.info[0]['Family'] == 6
 
-    def _is_Athlon64(self):
-        return self.is_AMD() and self.info[0]['Family']==15 \
-               and self.info[0]['Model']==4
+    # To reliably distinguish between the different types of AMD64 chips
+    # (Athlon64, Operton, Athlon64 X2, Semperon, Turion 64, etc.) would
+    # require looking at the 'brand' from cpuid
 
-    def _is_Opteron(self):
-        return self.is_AMD() and self.info[0]['Family']==15 \
-               and self.info[0]['Model']==5
+    def _is_AMD64(self):
+        return self.is_AMD() and self.info[0]['Family'] == 15
 
     # Intel
 
@@ -626,6 +593,14 @@
     def _is_PentiumIV(self):
         return self.is_Intel() and self.info[0]['Family']==15
 
+    def _is_PentiumM(self):
+        return self.is_Intel() and self.info[0]['Family'] == 6 \
+               and self.info[0]['Model'] in [9, 13, 14]
+
+    def _is_Core2(self):
+        return self.is_Intel() and self.info[0]['Family'] == 6 \
+               and self.info[0]['Model'] in [15, 16, 17]
+
     # Varia
 
     def _is_singleCPU(self):
@@ -640,6 +615,8 @@
                    or (self.info[0]['Family'] in [6,15])
         elif self.is_AMD():
             return self.info[0]['Family'] in [5,6,15]
+        else:
+            return False
 
     def _has_sse(self):
         if self.is_Intel():
@@ -650,32 +627,39 @@
             return (self.info[0]['Family']==6 and \
                     self.info[0]['Model'] in [6,7,8,10]) \
                     or self.info[0]['Family']==15
+        else:
+            return False
 
     def _has_sse2(self):
-        return self.info[0]['Family']==15
+        if self.is_Intel():
+            return self.is_Pentium4() or self.is_PentiumM() \
+                   or self.is_Core2()
+        elif self.is_AMD():
+            return self.is_AMD64()
+        else:
+            return False
 
     def _has_3dnow(self):
-        # XXX: does only AMD have 3dnow??
         return self.is_AMD() and self.info[0]['Family'] in [5,6,15]
 
     def _has_3dnowext(self):
         return self.is_AMD() and self.info[0]['Family'] in [6,15]
 
-if sys.platform[:5] == 'linux': # variations: linux2,linux-i386 (any others?)
-    cpuinfo = linux_cpuinfo
-elif sys.platform[:4] == 'irix':
-    cpuinfo = irix_cpuinfo
+if sys.platform.startswith('linux'): # variations: linux2,linux-i386 (any others?)
+    cpuinfo = LinuxCPUInfo
+elif sys.platform.startswith('irix'):
+    cpuinfo = IRIXCPUInfo
 elif sys.platform == 'darwin':
-    cpuinfo = darwin_cpuinfo
-elif sys.platform[:5] == 'sunos':
-    cpuinfo = sunos_cpuinfo
-elif sys.platform[:5] == 'win32':
-    cpuinfo = win32_cpuinfo
-elif sys.platform[:6] == 'cygwin':
-    cpuinfo = linux_cpuinfo
+    cpuinfo = DarwinCPUInfo
+elif sys.platform.startswith('sunos'):
+    cpuinfo = SunOSCPUInfo
+elif sys.platform.startswith('win32'):
+    cpuinfo = Win32CPUInfo
+elif sys.platform.startswith('cygwin'):
+    cpuinfo = LinuxCPUInfo
 #XXX: other OS's. Eg. use _winreg on Win32. Or os.uname on unices.
 else:
-    cpuinfo = cpuinfo_base
+    cpuinfo = CPUInfoBase
 
 cpu = cpuinfo()
 



More information about the Numpy-svn mailing list