Changeset eafc9fa in sasmodels


Ignore:
Timestamp:
Jan 30, 2016 7:39:59 PM (8 years ago)
Author:
Paul Kienzle <pkienzle@…>
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:
5925e90
Parents:
823e620
Message:

refactor kernel wrappers to simplify q input handling

Location:
sasmodels
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/core.py

    rd07c883 reafc9fa  
    118118    Return a computation kernel from the model definition and the q input. 
    119119    """ 
    120     model_input = model.make_input(q_vectors) 
    121     return model(model_input) 
     120    return model(q_vectors) 
    122121 
    123122def get_weights(info, pars, name): 
  • sasmodels/data.py

    r299edd2 reafc9fa  
    121121        # TODO: why is 1D mask False and 2D mask True? 
    122122        self.mask = (np.isnan(y) if y is not None 
    123                      else np.zeros_like(x,'b') if x is not None 
     123                     else np.zeros_like(x, 'b') if x is not None 
    124124                     else None) 
    125125        self._xaxis, self._xunit = "x", "" 
     
    350350    """ 
    351351    def wrapper(*args, **kw): 
     352        """ 
     353        Trap and print errors from function %s 
     354        """%fn.__name__ 
    352355        try: 
    353356            return fn(*args, **kw) 
  • sasmodels/direct_model.py

    r803f835 reafc9fa  
    149149    def _calc_theory(self, pars, cutoff=0.0): 
    150150        if self._kernel is None: 
    151             q_input = self._model.make_input(self._kernel_inputs) 
    152             self._kernel = self._model(q_input)  # pylint: disable=attribute-defined-outside-init 
     151            self._kernel = make_kernel(self._model, self._kernel_inputs)  # pylint: disable=attribute-defined-outside-init 
    153152 
    154153        Iq_calc = call_kernel(self._kernel, pars, cutoff=cutoff) 
     
    177176        # Note: _interpret_data defines the model attributes 
    178177        self._interpret_data(data, model) 
    179         self.kernel = make_kernel(self.model, self._kernel_inputs) 
    180178 
    181179    def __call__(self, **pars): 
  • sasmodels/generate.py

    r823e620 reafc9fa  
    313313    raise ValueError("%r not found in %s" % (filename, search_path)) 
    314314 
    315 def sources(info): 
     315def model_sources(info): 
    316316    """ 
    317317    Return a list of the sources file paths for the module. 
     
    465465 
    466466    # Load additional sources 
    467     source = [open(f).read() for f in sources(info)] 
     467    source = [open(f).read() for f in model_sources(info)] 
    468468 
    469469    # Prepare defines 
  • sasmodels/kernelcl.py

    r823e620 reafc9fa  
    11""" 
    2 GPU support through OpenCL 
     2GPU driver for C kernels 
    33 
    44There should be a single GPU environment running on the system.  This 
     
    152152 
    153153 
    154 def make_result(self, size): 
    155     self.res = np.empty(size, dtype=self.dtype) 
    156     self.res_b = cl.Buffer(self.program.context, mf.READ_WRITE, self.res.nbytes) 
    157     return self.res, self.res_b 
    158  
    159  
    160154# for now, this returns one device in the context 
    161155# TODO: create a context that contains all devices on all platforms 
     
    183177 
    184178    def has_type(self, dtype): 
     179        """ 
     180        Return True if all devices support a given type. 
     181        """ 
    185182        dtype = generate.F32 if dtype == 'fast' else np.dtype(dtype) 
    186183        return all(has_type(d, dtype) for d in self.context.devices) 
    187184 
    188185    def _create_some_context(self): 
     186        """ 
     187        Protected call to cl.create_some_context without interactivity.  Use 
     188        this if PYOPENCL_CTX is set in the environment.  Sets the *context* 
     189        attribute. 
     190        """ 
    189191        try: 
    190192            self.context = cl.create_some_context(interactive=False) 
     
    195197 
    196198    def compile_program(self, name, source, dtype, fast=False): 
     199        """ 
     200        Compile the program for the device in the given context. 
     201        """ 
    197202        key = "%s-%s-%s"%(name, dtype, fast) 
    198203        if key not in self.compiled: 
     
    204209 
    205210    def release_program(self, name): 
     211        """ 
     212        Free memory associated with the program on the device. 
     213        """ 
    206214        if name in self.compiled: 
    207215            self.compiled[name].release() 
     
    209217 
    210218def _get_default_context(): 
     219    """ 
     220    Get an OpenCL context, preferring GPU over CPU. 
     221    """ 
    211222    default = None 
    212223    for platform in cl.get_platforms(): 
     
    246257 
    247258    def __getstate__(self): 
    248         state = self.__dict__.copy() 
    249         state['program'] = None 
    250         return state 
     259        return self.info, self.source, self.dtype, self.fast 
    251260 
    252261    def __setstate__(self, state): 
    253         self.__dict__ = state.copy() 
    254  
    255     def __call__(self, q_input): 
    256         if self.dtype != q_input.dtype: 
    257             raise TypeError("data is %s kernel is %s" 
    258                             % (q_input.dtype, self.dtype)) 
     262        self.info, self.source, self.dtype, self.fast = state 
     263        self.program = None 
     264 
     265    def __call__(self, q_vectors): 
    259266        if self.program is None: 
    260267            compiler = environment().compile_program 
    261268            self.program = compiler(self.info['name'], self.source, self.dtype, 
    262269                                    self.fast) 
    263         kernel_name = generate.kernel_name(self.info, q_input.is_2D) 
     270        is_2d = len(q_vectors) == 2 
     271        kernel_name = generate.kernel_name(self.info, is_2d) 
    264272        kernel = getattr(self.program, kernel_name) 
    265         return GpuKernel(kernel, self.info, q_input) 
     273        return GpuKernel(kernel, self.info, q_vectors, self.dtype) 
    266274 
    267275    def release(self): 
     276        """ 
     277        Free the resources associated with the model. 
     278        """ 
    268279        if self.program is not None: 
    269280            environment().release_program(self.info['name']) 
    270281            self.program = None 
    271282 
    272     def make_input(self, q_vectors): 
    273         """ 
    274         Make q input vectors available to the model. 
    275  
    276         Note that each model needs its own q vector even if the case of 
    277         mixture models because some models may be OpenCL, some may be 
    278         ctypes and some may be pure python. 
    279         """ 
    280         return GpuInput(q_vectors, dtype=self.dtype) 
     283    def __del__(self): 
     284        self.release() 
    281285 
    282286# TODO: check that we don't need a destructor for buffers which go out of scope 
     
    304308        self.nq = q_vectors[0].size 
    305309        self.dtype = np.dtype(dtype) 
    306         self.is_2D = (len(q_vectors) == 2) 
     310        self.is_2d = (len(q_vectors) == 2) 
    307311        # TODO: stretch input based on get_warp() 
    308312        # not doing it now since warp depends on kernel, which is not known 
     
    317321 
    318322    def release(self): 
     323        """ 
     324        Free the memory. 
     325        """ 
    319326        for b in self.q_buffers: 
    320327            b.release() 
    321328        self.q_buffers = [] 
    322329 
     330    def __del__(self): 
     331        self.release() 
     332 
    323333class GpuKernel(object): 
    324334    """ 
    325335    Callable SAS kernel. 
    326336 
    327     *kernel* is the GpuKernel object to call. 
     337    *kernel* is the GpuKernel object to call 
    328338 
    329339    *info* is the module information 
    330340 
    331     *q_input* is the DllInput q vectors at which the kernel should be 
    332     evaluated. 
     341    *q_vectors* is the q vectors at which the kernel should be evaluated 
     342 
     343    *dtype* is the kernel precision 
    333344 
    334345    The resulting call method takes the *pars*, a list of values for 
     
    340351    Call :meth:`release` when done with the kernel instance. 
    341352    """ 
    342     def __init__(self, kernel, info, q_input): 
    343         self.q_input = q_input 
     353    def __init__(self, kernel, info, q_vectors, dtype): 
     354        q_input = GpuInput(q_vectors, dtype) 
    344355        self.kernel = kernel 
    345356        self.info = info 
    346357        self.res = np.empty(q_input.nq, q_input.dtype) 
    347         dim = '2d' if q_input.is_2D else '1d' 
     358        dim = '2d' if q_input.is_2d else '1d' 
    348359        self.fixed_pars = info['partype']['fixed-' + dim] 
    349360        self.pd_pars = info['partype']['pd-' + dim] 
     
    358369                                q_input.global_size[0] * q_input.dtype.itemsize) 
    359370                      for _ in env.queues] 
    360  
     371        self.q_input = q_input 
    361372 
    362373    def __call__(self, fixed_pars, pd_pars, cutoff=1e-5): 
     
    399410 
    400411    def release(self): 
     412        """ 
     413        Release resources associated with the kernel. 
     414        """ 
    401415        for b in self.loops_b: 
    402416            b.release() 
     
    405419            b.release() 
    406420        self.res_b = [] 
     421        self.q_input.release() 
    407422 
    408423    def __del__(self): 
  • sasmodels/kerneldll.py

    r823e620 reafc9fa  
    11r""" 
    2 C types wrapper for sasview models. 
     2DLL driver for C kernels 
    33 
    44The global attribute *ALLOW_SINGLE_PRECISION_DLLS* should be set to *True* if 
     
    4444directory for this application, then OpenMP should be supported. 
    4545""" 
     46from __future__ import print_function 
    4647 
    4748import sys 
     
    139140 
    140141    source = generate.convert_type(source, dtype) 
    141     source_files = generate.sources(info) + [info['filename']] 
     142    source_files = generate.model_sources(info) + [info['filename']] 
    142143    dll = dll_path(info, dtype) 
    143144    newest = max(os.path.getmtime(f) for f in source_files) 
     
    218219 
    219220    def __getstate__(self): 
    220         return {'info': self.info, 'dllpath': self.dllpath, 'dll': None} 
     221        return self.info, self.dllpath 
    221222 
    222223    def __setstate__(self, state): 
    223         self.__dict__ = state 
    224  
    225     def __call__(self, q_input): 
    226         if self.dtype != q_input.dtype: 
    227             raise TypeError("data is %s kernel is %s" % (q_input.dtype, self.dtype)) 
     224        self.info, self.dllpath = state 
     225        self.dll = None 
     226 
     227    def __call__(self, q_vectors): 
     228        q_input = PyInput(q_vectors, self.dtype) 
    228229        if self.dll is None: self._load_dll() 
    229         kernel = self.Iqxy if q_input.is_2D else self.Iq 
     230        kernel = self.Iqxy if q_input.is_2d else self.Iq 
    230231        return DllKernel(kernel, self.info, q_input) 
    231232 
    232     # pylint: disable=no-self-use 
    233     def make_input(self, q_vectors): 
    234         """ 
    235         Make q input vectors available to the model. 
    236  
    237         Note that each model needs its own q vector even if the case of 
    238         mixture models because some models may be OpenCL, some may be 
    239         ctypes and some may be pure python. 
    240         """ 
    241         return PyInput(q_vectors, dtype=self.dtype) 
    242  
    243233    def release(self): 
     234        """ 
     235        Release any resources associated with the model. 
     236        """ 
    244237        pass # TODO: should release the dll 
    245238 
     
    269262        self.kernel = kernel 
    270263        self.res = np.empty(q_input.nq, q_input.dtype) 
    271         dim = '2d' if q_input.is_2D else '1d' 
     264        dim = '2d' if q_input.is_2d else '1d' 
    272265        self.fixed_pars = info['partype']['fixed-'+dim] 
    273266        self.pd_pars = info['partype']['pd-'+dim] 
     
    299292 
    300293    def release(self): 
     294        """ 
     295        Release any resources associated with the kernel. 
     296        """ 
    301297        pass 
  • sasmodels/kernelpy.py

    r4c2c535 reafc9fa  
     1""" 
     2Python driver for python kernels 
     3 
     4Calls the kernel with a vector of $q$ values for a single parameter set. 
     5Polydispersity is supported by looping over different parameter sets and 
     6summing the results.  The interface to :class:`PyModel` matches those for 
     7:class:`kernelcl.GpuModel` and :class:`kerneldll.DllModel`. 
     8""" 
    19import numpy as np 
    210from numpy import pi, cos 
     
    513 
    614class PyModel(object): 
     15    """ 
     16    Wrapper for pure python models. 
     17    """ 
    718    def __init__(self, info): 
    819        self.info = info 
    920 
    10     def __call__(self, q_input): 
    11         kernel = self.info['Iqxy'] if q_input.is_2D else self.info['Iq'] 
     21    def __call__(self, q_vectors): 
     22        q_input = PyInput(q_vectors, dtype=F64) 
     23        kernel = self.info['Iqxy'] if q_input.is_2d else self.info['Iq'] 
    1224        return PyKernel(kernel, self.info, q_input) 
    1325 
    14     # pylint: disable=no-self-use 
    15     def make_input(self, q_vectors): 
    16         return PyInput(q_vectors, dtype=F64) 
    17  
    1826    def release(self): 
     27        """ 
     28        Free resources associated with the model. 
     29        """ 
    1930        pass 
    2031 
     
    4152        self.nq = q_vectors[0].size 
    4253        self.dtype = dtype 
    43         self.is_2D = (len(q_vectors) == 2) 
     54        self.is_2d = (len(q_vectors) == 2) 
    4455        self.q_vectors = [np.ascontiguousarray(q, self.dtype) for q in q_vectors] 
    4556        self.q_pointers = [q.ctypes.data for q in self.q_vectors] 
    4657 
    4758    def release(self): 
     59        """ 
     60        Free resources associated with the model inputs. 
     61        """ 
    4862        self.q_vectors = [] 
    4963 
     
    7185        self.q_input = q_input 
    7286        self.res = np.empty(q_input.nq, q_input.dtype) 
    73         dim = '2d' if q_input.is_2D else '1d' 
     87        dim = '2d' if q_input.is_2d else '1d' 
    7488        # Loop over q unless user promises that the kernel is vectorized by 
    7589        # taggining it with vectorized=True 
     
    7791            if dim == '2d': 
    7892                def vector_kernel(qx, qy, *args): 
     93                    """ 
     94                    Vectorized 2D kernel. 
     95                    """ 
    7996                    return np.array([kernel(qxi, qyi, *args) 
    8097                                     for qxi, qyi in zip(qx, qy)]) 
    8198            else: 
    8299                def vector_kernel(q, *args): 
     100                    """ 
     101                    Vectorized 1D kernel. 
     102                    """ 
    83103                    return np.array([kernel(qi, *args) 
    84104                                     for qi in q]) 
     
    122142 
    123143    def release(self): 
     144        """ 
     145        Free resources associated with the kernel. 
     146        """ 
    124147        self.q_input = None 
    125148 
  • sasmodels/sasview_model.py

    r9404dd3 reafc9fa  
    283283        """ 
    284284        q_vectors = [np.asarray(q) for q in args] 
    285         fn = self._model(self._model.make_input(q_vectors)) 
     285        fn = self._model(q_vectors) 
    286286        pars = [self.params[v] for v in fn.fixed_pars] 
    287287        pd_pars = [self._get_weights(p) for p in fn.pd_pars] 
Note: See TracChangeset for help on using the changeset viewer.