diff --git a/Pipfile b/Pipfile index 4eff8a5..480a352 100644 --- a/Pipfile +++ b/Pipfile @@ -9,6 +9,7 @@ numpy = "*" [dev-packages] pytest = "*" pillow = "*" +cpuid = "*" [requires] python_version = "3.6" diff --git a/cpuid/LICENSE b/cpuid/LICENSE deleted file mode 100644 index af36480..0000000 --- a/cpuid/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 Anders Høst - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/cpuid/__init__.py b/cpuid/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/cpuid/cpuid.py b/cpuid/cpuid.py deleted file mode 100644 index 9abbf84..0000000 --- a/cpuid/cpuid.py +++ /dev/null @@ -1,154 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (c) 2018 Anders Høst -# - -from __future__ import print_function - -import platform -import os -import ctypes -from ctypes import c_uint32, c_int, c_long, c_ulong, c_size_t, c_void_p, POINTER, CFUNCTYPE - -# Posix x86_64: -# Three first call registers : RDI, RSI, RDX -# Volatile registers : RAX, RCX, RDX, RSI, RDI, R8-11 - -# Windows x86_64: -# Three first call registers : RCX, RDX, R8 -# Volatile registers : RAX, RCX, RDX, R8-11 - -# cdecl 32 bit: -# Three first call registers : Stack (%esp) -# Volatile registers : EAX, ECX, EDX - -_POSIX_64_OPC = [ - 0x53, # push %rbx - 0x89, 0xf0, # mov %esi,%eax - 0x89, 0xd1, # mov %edx,%ecx - 0x0f, 0xa2, # cpuid - 0x89, 0x07, # mov %eax,(%rdi) - 0x89, 0x5f, 0x04, # mov %ebx,0x4(%rdi) - 0x89, 0x4f, 0x08, # mov %ecx,0x8(%rdi) - 0x89, 0x57, 0x0c, # mov %edx,0xc(%rdi) - 0x5b, # pop %rbx - 0xc3 # retq -] - -_WINDOWS_64_OPC = [ - 0x53, # push %rbx - 0x89, 0xd0, # mov %edx,%eax - 0x49, 0x89, 0xc9, # mov %rcx,%r9 - 0x44, 0x89, 0xc1, # mov %r8d,%ecx - 0x0f, 0xa2, # cpuid - 0x41, 0x89, 0x01, # mov %eax,(%r9) - 0x41, 0x89, 0x59, 0x04, # mov %ebx,0x4(%r9) - 0x41, 0x89, 0x49, 0x08, # mov %ecx,0x8(%r9) - 0x41, 0x89, 0x51, 0x0c, # mov %edx,0xc(%r9) - 0x5b, # pop %rbx - 0xc3 # retq -] - -_CDECL_32_OPC = [ - 0x53, # push %ebx - 0x57, # push %edi - 0x8b, 0x7c, 0x24, 0x0c, # mov 0xc(%esp),%edi - 0x8b, 0x44, 0x24, 0x10, # mov 0x10(%esp),%eax - 0x8b, 0x4c, 0x24, 0x14, # mov 0x14(%esp),%ecx - 0x0f, 0xa2, # cpuid - 0x89, 0x07, # mov %eax,(%edi) - 0x89, 0x5f, 0x04, # mov %ebx,0x4(%edi) - 0x89, 0x4f, 0x08, # mov %ecx,0x8(%edi) - 0x89, 0x57, 0x0c, # mov %edx,0xc(%edi) - 0x5f, # pop %edi - 0x5b, # pop %ebx - 0xc3 # ret -] - -is_windows = os.name == "nt" -is_64bit = ctypes.sizeof(ctypes.c_voidp) == 8 - -class CPUID_struct(ctypes.Structure): - _fields_ = [(r, c_uint32) for r in ("eax", "ebx", "ecx", "edx")] - -class CPUID(object): - def __init__(self): - if platform.machine() not in ("AMD64", "x86_64", "x86", "i686"): - raise SystemError("Only available for x86") - - if is_windows: - if is_64bit: - # VirtualAlloc seems to fail under some weird - # circumstances when ctypes.windll.kernel32 is - # used under 64 bit Python. CDLL fixes this. - self.win = ctypes.CDLL("kernel32.dll") - opc = _WINDOWS_64_OPC - else: - # Here ctypes.windll.kernel32 is needed to get the - # right DLL. Otherwise it will fail when running - # 32 bit Python on 64 bit Windows. - self.win = ctypes.windll.kernel32 - opc = _CDECL_32_OPC - else: - opc = _POSIX_64_OPC if is_64bit else _CDECL_32_OPC - - size = len(opc) - code = (ctypes.c_ubyte * size)(*opc) - - if is_windows: - self.win.VirtualAlloc.restype = c_void_p - self.win.VirtualAlloc.argtypes = [ctypes.c_void_p, ctypes.c_size_t, ctypes.c_ulong, ctypes.c_ulong] - self.addr = self.win.VirtualAlloc(None, size, 0x1000, 0x40) - if not self.addr: - raise MemoryError("Could not allocate RWX memory") - else: - self.libc = ctypes.cdll.LoadLibrary(None) - self.libc.valloc.restype = ctypes.c_void_p - self.libc.valloc.argtypes = [ctypes.c_size_t] - self.addr = self.libc.valloc(size) - if not self.addr: - raise MemoryError("Could not allocate memory") - - self.libc.mprotect.restype = c_int - self.libc.mprotect.argtypes = [c_void_p, c_size_t, c_int] - ret = self.libc.mprotect(self.addr, size, 1 | 2 | 4) - if ret != 0: - raise OSError("Failed to set RWX") - - - ctypes.memmove(self.addr, code, size) - - func_type = CFUNCTYPE(None, POINTER(CPUID_struct), c_uint32, c_uint32) - self.func_ptr = func_type(self.addr) - - def __call__(self, eax, ecx=0): - struct = CPUID_struct() - self.func_ptr(struct, eax, ecx) - return struct.eax, struct.ebx, struct.ecx, struct.edx - - def __del__(self): - if is_windows: - self.win.VirtualFree.restype = c_long - self.win.VirtualFree.argtypes = [c_void_p, c_size_t, c_ulong] - self.win.VirtualFree(self.addr, 0, 0x8000) - elif self.libc: - # Seems to throw exception when the program ends and - # libc is cleaned up before the object? - self.libc.free.restype = None - self.libc.free.argtypes = [c_void_p] - self.libc.free(self.addr) - -if __name__ == "__main__": - def valid_inputs(): - cpuid = CPUID() - for eax in (0x0, 0x80000000): - highest, _, _, _ = cpuid(eax) - while eax <= highest: - regs = cpuid(eax) - yield (eax, regs) - eax += 1 - - print(" ".join(x.ljust(8) for x in ("CPUID", "A", "B", "C", "D")).strip()) - for eax, regs in valid_inputs(): - print("%08x" % eax, " ".join("%08x" % reg for reg in regs)) - diff --git a/setup.py b/setup.py index 2dbe486..db6ad08 100755 --- a/setup.py +++ b/setup.py @@ -106,17 +106,18 @@ def _check_openmp(): return _compile_and_check(omp_test, ['-fopenmp', '-lgomp']) def _check_avx2(): - from cpuid.cpuid import CPUID + import cpuid try: # Invoke CPUID instruction with eax 0x7 # ECX bit 5: AVX2 support # For more information, refer to https://en.wikipedia.org/wiki/CPUID input_eax = 0x7 - output_eax, output_ebx, output_ecx, output_edx = CPUID()(input_eax) + output_eax, output_ebx, output_ecx, output_edx = cpuid.cpuid_count(input_eax, 0) bits = bin(output_ebx)[::-1] avx2_support = bits[5] return avx2_support == '1' - except: + except Exception as e: + print(f"Failed to check AVX2 support: {e}") return False def _check_neon(): @@ -170,11 +171,11 @@ def _check_neon(): setup( name="fast-slic", - version="0.4.0", + version="0.4.1", description="Fast Slic Superpixel Implementation", author="Alchan Kim", author_email="a9413miky@gmail.com", - setup_requires = ["cython", "numpy"], + setup_requires = ["cython", "numpy", "cpuid"], install_requires=["numpy"], python_requires=">=3.5", license="MIT",