Changeset f619de7 in sasmodels for sasmodels/kerneldll.py
- Timestamp:
- Apr 11, 2016 9:14:50 AM (8 years ago)
- Branches:
- master, core_shell_microgels, costrafo411, magnetic_model, release_v0.94, release_v0.95, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
- Children:
- 7ae2b7f
- Parents:
- 9a943d0
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
sasmodels/kerneldll.py
r6d6508e rf619de7 56 56 from . import generate 57 57 from . import details 58 from .kernelpy import PyInput, PyModel 58 from .kernel import KernelModel, Kernel 59 from .kernelpy import PyInput 59 60 from .exception import annotate_exception 61 from .generate import F16, F32, F64 62 63 try: 64 from typing import Tuple, Callable, Any 65 from .modelinfo import ModelInfo 66 from .details import CallDetails 67 except ImportError: 68 pass 60 69 61 70 # Compiler platform details … … 91 100 92 101 def dll_name(model_info, dtype): 102 # type: (ModelInfo, np.dtype) -> str 93 103 """ 94 104 Name of the dll containing the model. This is the base file name without … … 98 108 return "sas_%s%d"%(model_info.id, bits) 99 109 110 100 111 def dll_path(model_info, dtype): 112 # type: (ModelInfo, np.dtype) -> str 101 113 """ 102 114 Complete path to the dll for the model. Note that the dll may not … … 105 117 return os.path.join(DLL_PATH, dll_name(model_info, dtype)+".so") 106 118 107 def make_dll(source, model_info, dtype="double"): 108 """ 109 Load the compiled model defined by *kernel_module*. 110 111 Recompile if any files are newer than the model file. 119 120 def make_dll(source, model_info, dtype=F64): 121 # type: (str, ModelInfo, np.dtype) -> str 122 """ 123 Returns the path to the compiled model defined by *kernel_module*. 124 125 If the model has not been compiled, or if the source file(s) are newer 126 than the dll, then *make_dll* will compile the model before returning. 127 This routine does not load the resulting dll. 112 128 113 129 *dtype* is a numpy floating point precision specifier indicating whether 114 the model should be single or double precision. The default is double115 precision.116 117 The DLL is not loaded until the kernel is called so models can118 be defined without using too many resources.130 the model should be single, double or long double precision. The default 131 is double precision, *np.dtype('d')*. 132 133 Set *sasmodels.ALLOW_SINGLE_PRECISION_DLLS* to False if single precision 134 models are not allowed as DLLs. 119 135 120 136 Set *sasmodels.kerneldll.DLL_PATH* to the compiled dll output path. 121 137 The default is the system temporary directory. 122 123 Set *sasmodels.ALLOW_SINGLE_PRECISION_DLLS* to True if single precision 124 models are allowed as DLLs. 125 """ 126 if callable(model_info.Iq): 127 return PyModel(model_info) 128 129 dtype = np.dtype(dtype) 130 if dtype == generate.F16: 138 """ 139 if dtype == F16: 131 140 raise ValueError("16 bit floats not supported") 132 if dtype == generate.F32 and not ALLOW_SINGLE_PRECISION_DLLS:133 dtype = generate.F64 # Force 64-bit dll134 135 source = generate.convert_type(source, dtype) 141 if dtype == F32 and not ALLOW_SINGLE_PRECISION_DLLS: 142 dtype = F64 # Force 64-bit dll 143 # Note: dtype may be F128 for long double precision 144 136 145 newest = generate.timestamp(model_info) 137 146 dll = dll_path(model_info, dtype) … … 139 148 basename = dll_name(model_info, dtype) + "_" 140 149 fid, filename = tempfile.mkstemp(suffix=".c", prefix=basename) 150 source = generate.convert_type(source, dtype) 141 151 os.fdopen(fid, "w").write(source) 142 152 command = COMPILE%{"source":filename, "output":dll} … … 152 162 153 163 154 def load_dll(source, model_info, dtype="double"): 164 def load_dll(source, model_info, dtype=F64): 165 # type: (str, ModelInfo, np.dtype) -> "DllModel" 155 166 """ 156 167 Create and load a dll corresponding to the source, info pair returned … … 163 174 return DllModel(filename, model_info, dtype=dtype) 164 175 165 class DllModel(object): 176 177 class DllModel(KernelModel): 166 178 """ 167 179 ctypes wrapper for a single model. … … 179 191 180 192 def __init__(self, dllpath, model_info, dtype=generate.F32): 193 # type: (str, ModelInfo, np.dtype) -> None 181 194 self.info = model_info 182 195 self.dllpath = dllpath 183 self. dll = None196 self._dll = None # type: ct.CDLL 184 197 self.dtype = np.dtype(dtype) 185 198 186 199 def _load_dll(self): 200 # type: () -> None 187 201 #print("dll", self.dllpath) 188 202 try: 189 self. dll = ct.CDLL(self.dllpath)203 self._dll = ct.CDLL(self.dllpath) 190 204 except: 191 205 annotate_exception("while loading "+self.dllpath) … … 198 212 # int, int, int, int*, double*, double*, double*, double*, double*, double 199 213 argtypes = [c_int32]*3 + [c_void_p]*5 + [fp] 200 self. Iq = self.dll[generate.kernel_name(self.info,False)]201 self. Iqxy = self.dll[generate.kernel_name(self.info,True)]202 self. Iq.argtypes = argtypes203 self. Iqxy.argtypes = argtypes214 self._Iq = self._dll[generate.kernel_name(self.info, is_2d=False)] 215 self._Iqxy = self._dll[generate.kernel_name(self.info, is_2d=True)] 216 self._Iq.argtypes = argtypes 217 self._Iqxy.argtypes = argtypes 204 218 205 219 def __getstate__(self): 220 # type: () -> Tuple[ModelInfo, str] 206 221 return self.info, self.dllpath 207 222 208 223 def __setstate__(self, state): 224 # type: (Tuple[ModelInfo, str]) -> None 209 225 self.info, self.dllpath = state 210 self. dll = None226 self._dll = None 211 227 212 228 def make_kernel(self, q_vectors): 229 # type: (List[np.ndarray]) -> DllKernel 213 230 q_input = PyInput(q_vectors, self.dtype) 214 if self.dll is None: self._load_dll() 215 kernel = self.Iqxy if q_input.is_2d else self.Iq 231 # Note: pickle not supported for DllKernel 232 if self._dll is None: 233 self._load_dll() 234 kernel = self._Iqxy if q_input.is_2d else self._Iq 216 235 return DllKernel(kernel, self.info, q_input) 217 236 218 237 def release(self): 238 # type: () -> None 219 239 """ 220 240 Release any resources associated with the model. … … 225 245 libHandle = dll._handle 226 246 #libHandle = ct.c_void_p(dll._handle) 227 del dll, self. dll228 self. dll = None247 del dll, self._dll 248 self._dll = None 229 249 #_ctypes.FreeLibrary(libHandle) 230 250 ct.windll.kernel32.FreeLibrary(libHandle) … … 233 253 234 254 235 class DllKernel( object):255 class DllKernel(Kernel): 236 256 """ 237 257 Callable SAS kernel. … … 253 273 """ 254 274 def __init__(self, kernel, model_info, q_input): 275 # type: (Callable[[], np.ndarray], ModelInfo, PyInput) -> None 255 276 self.kernel = kernel 256 277 self.info = model_info … … 261 282 262 283 def __call__(self, call_details, weights, values, cutoff): 284 # type: (CallDetails, np.ndarray, np.ndarray, float) -> np.ndarray 263 285 real = (np.float32 if self.q_input.dtype == generate.F32 264 286 else np.float64 if self.q_input.dtype == generate.F64 … … 282 304 real(cutoff), # cutoff 283 305 ] 284 self.kernel(*args) 306 self.kernel(*args) # type: ignore 285 307 return self.result[:-3] 286 308 287 309 def release(self): 310 # type: () -> None 288 311 """ 289 312 Release any resources associated with the kernel. 290 313 """ 291 pass314 self.q_input.release()
Note: See TracChangeset
for help on using the changeset viewer.