Changeset 3221de0 in sasmodels


Ignore:
Timestamp:
Feb 1, 2018 7:40:30 AM (6 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, core_shell_microgels, magnetic_model, ticket-1257-vesicle-product, ticket_1156, ticket_1265_superball, ticket_822_more_unit_tests
Children:
b4272a2
Parents:
b3af1c2
Message:

restructure handling of opencl flags so it works with sasview

Location:
sasmodels
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • sasmodels/compare.py

    r2a7e20e r3221de0  
    4040from . import core 
    4141from . import kerneldll 
     42from . import kernelcl 
    4243from .data import plot_theory, empty_data1D, empty_data2D, load_data 
    4344from .direct_model import DirectModel, get_mesh 
     
    623624 
    624625 
     626def time_calculation(calculator, pars, evals=1): 
     627    # type: (Calculator, ParameterSet, int) -> Tuple[np.ndarray, float] 
     628    """ 
     629    Compute the average calculation time over N evaluations. 
     630 
     631    An additional call is generated without polydispersity in order to 
     632    initialize the calculation engine, and make the average more stable. 
     633    """ 
     634    # initialize the code so time is more accurate 
     635    if evals > 1: 
     636        calculator(**suppress_pd(pars)) 
     637    toc = tic() 
     638    # make sure there is at least one eval 
     639    value = calculator(**pars) 
     640    for _ in range(evals-1): 
     641        value = calculator(**pars) 
     642    average_time = toc()*1000. / evals 
     643    #print("I(q)",value) 
     644    return value, average_time 
     645 
     646def make_data(opts): 
     647    # type: (Dict[str, Any]) -> Tuple[Data, np.ndarray] 
     648    """ 
     649    Generate an empty dataset, used with the model to set Q points 
     650    and resolution. 
     651 
     652    *opts* contains the options, with 'qmax', 'nq', 'res', 
     653    'accuracy', 'is2d' and 'view' parsed from the command line. 
     654    """ 
     655    qmin, qmax, nq, res = opts['qmin'], opts['qmax'], opts['nq'], opts['res'] 
     656    if opts['is2d']: 
     657        q = np.linspace(-qmax, qmax, nq)  # type: np.ndarray 
     658        data = empty_data2D(q, resolution=res) 
     659        data.accuracy = opts['accuracy'] 
     660        set_beam_stop(data, qmin) 
     661        index = ~data.mask 
     662    else: 
     663        if opts['view'] == 'log' and not opts['zero']: 
     664            q = np.logspace(math.log10(qmin), math.log10(qmax), nq) 
     665        else: 
     666            q = np.linspace(qmin, qmax, nq) 
     667        if opts['zero']: 
     668            q = np.hstack((0, q)) 
     669        data = empty_data1D(q, resolution=res) 
     670        index = slice(None, None) 
     671    return data, index 
     672 
    625673DTYPE_MAP = { 
    626674    'half': '16', 
     
    643691    Return a model calculator using the OpenCL calculation engine. 
    644692    """ 
    645     if not core.HAVE_OPENCL: 
    646         raise RuntimeError("OpenCL not available") 
    647     model = core.build_model(model_info, dtype=dtype, platform="ocl") 
    648     calculator = DirectModel(data, model, cutoff=cutoff) 
    649     calculator.engine = "OCL%s"%DTYPE_MAP[str(model.dtype)] 
    650     return calculator 
    651693 
    652694def eval_ctypes(model_info, data, dtype='double', cutoff=0.): 
     
    660702    return calculator 
    661703 
    662 def time_calculation(calculator, pars, evals=1): 
    663     # type: (Calculator, ParameterSet, int) -> Tuple[np.ndarray, float] 
    664     """ 
    665     Compute the average calculation time over N evaluations. 
    666  
    667     An additional call is generated without polydispersity in order to 
    668     initialize the calculation engine, and make the average more stable. 
    669     """ 
    670     # initialize the code so time is more accurate 
    671     if evals > 1: 
    672         calculator(**suppress_pd(pars)) 
    673     toc = tic() 
    674     # make sure there is at least one eval 
    675     value = calculator(**pars) 
    676     for _ in range(evals-1): 
    677         value = calculator(**pars) 
    678     average_time = toc()*1000. / evals 
    679     #print("I(q)",value) 
    680     return value, average_time 
    681  
    682 def make_data(opts): 
    683     # type: (Dict[str, Any]) -> Tuple[Data, np.ndarray] 
    684     """ 
    685     Generate an empty dataset, used with the model to set Q points 
    686     and resolution. 
    687  
    688     *opts* contains the options, with 'qmax', 'nq', 'res', 
    689     'accuracy', 'is2d' and 'view' parsed from the command line. 
    690     """ 
    691     qmin, qmax, nq, res = opts['qmin'], opts['qmax'], opts['nq'], opts['res'] 
    692     if opts['is2d']: 
    693         q = np.linspace(-qmax, qmax, nq)  # type: np.ndarray 
    694         data = empty_data2D(q, resolution=res) 
    695         data.accuracy = opts['accuracy'] 
    696         set_beam_stop(data, qmin) 
    697         index = ~data.mask 
    698     else: 
    699         if opts['view'] == 'log' and not opts['zero']: 
    700             q = np.logspace(math.log10(qmin), math.log10(qmax), nq) 
    701         else: 
    702             q = np.linspace(qmin, qmax, nq) 
    703         if opts['zero']: 
    704             q = np.hstack((0, q)) 
    705         data = empty_data1D(q, resolution=res) 
    706         index = slice(None, None) 
    707     return data, index 
    708  
    709704def make_engine(model_info, data, dtype, cutoff, ngauss=0): 
    710705    # type: (ModelInfo, Data, str, float) -> Calculator 
     
    718713        set_integration_size(model_info, ngauss) 
    719714 
    720     if dtype is None or not dtype.endswith('!'): 
    721         return eval_opencl(model_info, data, dtype=dtype, cutoff=cutoff) 
    722     else: 
    723         return eval_ctypes(model_info, data, dtype=dtype[:-1], cutoff=cutoff) 
     715    if dtype != "default" and not dtype.endswith('!') and not kernelcl.use_opencl(): 
     716        raise RuntimeError("OpenCL not available " + kernelcl.OPENCL_ERROR) 
     717 
     718    model = core.build_model(model_info, dtype=dtype, platform="ocl") 
     719    calculator = DirectModel(data, model, cutoff=cutoff) 
     720    engine_type = calculator._model.__class__.__name__.replace('Model','').upper() 
     721    bits = calculator._model.dtype.itemsize*8 
     722    precision = "fast" if getattr(calculator._model, 'fast', False) else str(bits) 
     723    calculator.engine = "%s[%s]" % (engine_type, precision) 
     724    return calculator 
    724725 
    725726def _show_invalid(data, theory): 
  • sasmodels/core.py

    r6dba2f0 r3221de0  
    2525from . import custom 
    2626 
    27 # Other modules look for HAVE_OPENCL in core, not in kernelcl. 
    28 HAVE_OPENCL = kernelcl.HAVE_OPENCL 
    29  
    30 CUSTOM_MODEL_PATH = os.environ.get('SAS_MODELPATH', "") 
    31 if CUSTOM_MODEL_PATH == "": 
    32     CUSTOM_MODEL_PATH = joinpath(os.path.expanduser("~"), ".sasmodels", "custom_models") 
    33     if not os.path.isdir(CUSTOM_MODEL_PATH): 
    34         os.makedirs(CUSTOM_MODEL_PATH) 
    35  
    3627# pylint: disable=unused-import 
    3728try: 
     
    4233    pass 
    4334# pylint: enable=unused-import 
     35 
     36CUSTOM_MODEL_PATH = os.environ.get('SAS_MODELPATH', "") 
     37if CUSTOM_MODEL_PATH == "": 
     38    CUSTOM_MODEL_PATH = joinpath(os.path.expanduser("~"), ".sasmodels", "custom_models") 
     39    if not os.path.isdir(CUSTOM_MODEL_PATH): 
     40        os.makedirs(CUSTOM_MODEL_PATH) 
    4441 
    4542# TODO: refactor composite model support 
     
    271268    if platform is None: 
    272269        platform = "ocl" 
    273     if platform == "ocl" and not HAVE_OPENCL or not model_info.opencl: 
     270    if not kernelcl.use_opencl() or not model_info.opencl: 
    274271        platform = "dll" 
    275272 
  • sasmodels/kernelcl.py

    re59f60a r3221de0  
    5858import numpy as np  # type: ignore 
    5959 
     60 
     61# Attempt to setup opencl. This may fail if the opencl package is not 
     62# installed or if it is installed but there are no devices available. 
    6063try: 
    61     if os.environ.get("SAS_OPENCL", "").lower() == "none": 
    62         HAVE_OPENCL = False 
    63     else: 
    64         import pyopencl as cl  # type: ignore 
    65         from pyopencl import mem_flags as mf 
    66         from pyopencl.characterize import get_fast_inaccurate_build_options 
    67         # Ask OpenCL for the default context so that we know that one exists 
    68         cl.create_some_context(interactive=False) 
    69         HAVE_OPENCL = True 
     64    import pyopencl as cl  # type: ignore 
     65    from pyopencl import mem_flags as mf 
     66    from pyopencl.characterize import get_fast_inaccurate_build_options 
     67    # Ask OpenCL for the default context so that we know that one exists 
     68    cl.create_some_context(interactive=False) 
     69    HAVE_OPENCL = True 
     70    OPENCL_ERROR = "" 
    7071except Exception as exc: 
    71     warnings.warn("OpenCL startup failed with ***" 
    72                   + str(exc) + "***; using C compiler instead") 
    7372    HAVE_OPENCL = False 
     73    OPENCL_ERROR = str(exc) 
    7474 
    7575from . import generate 
     
    130130""" 
    131131 
     132def use_opencl(): 
     133    return HAVE_OPENCL and os.environ.get("SAS_OPENCL", "").lower() != "none" 
    132134 
    133135ENV = None 
     136def reset_environment(): 
     137    """ 
     138    Call to create a new OpenCL context, such as after a change to SAS_OPENCL. 
     139    """ 
     140    global ENV 
     141    ENV = GpuEnvironment() if use_opencl() else None 
     142 
    134143def environment(): 
    135144    # type: () -> "GpuEnvironment" 
     
    139148    This provides an OpenCL context and one queue per device. 
    140149    """ 
    141     global ENV 
    142     if ENV is None: 
    143         ENV = GpuEnvironment() 
     150    if not HAVE_OPENCL: 
     151        warnings.warn("OpenCL startup failed with ***" 
     152                      + OPENCL_ERROR + "***; using C compiler instead") 
     153    elif ENV is None: 
     154        reset_environment() 
    144155    return ENV 
    145156 
  • sasmodels/model_test.py

    rf354e46 r3221de0  
    6262from .exception import annotate_exception 
    6363from .modelinfo import expand_pars 
     64from .kernelcl import use_opencl 
    6465 
    6566# pylint: disable=unused-import 
     
    134135 
    135136            # test using dll if desired 
    136             if 'dll' in loaders or not core.HAVE_OPENCL: 
     137            if 'dll' in loaders or not use_opencl(): 
    137138                test_name = "%s-dll"%model_name 
    138139                test_method_name = "test_%s_dll" % model_info.id 
     
    145146 
    146147            # test using opencl if desired and available 
    147             if 'opencl' in loaders and core.HAVE_OPENCL: 
     148            if 'opencl' in loaders and use_opencl(): 
    148149                test_name = "%s-opencl"%model_name 
    149150                test_method_name = "test_%s_opencl" % model_info.id 
     
    367368 
    368369    # Build a test suite containing just the model 
    369     loaders = ['opencl'] if core.HAVE_OPENCL else ['dll'] 
     370    loaders = ['opencl'] if use_opencl() else ['dll'] 
    370371    models = [model] 
    371372    try: 
     
    424425        verbosity = 1 
    425426    if models and models[0] == 'opencl': 
    426         if not core.HAVE_OPENCL: 
     427        if not use_opencl(): 
    427428            print("opencl is not available") 
    428429            return 1 
     
    434435        models = models[1:] 
    435436    elif models and models[0] == 'opencl_and_dll': 
    436         loaders = ['opencl', 'dll'] if core.HAVE_OPENCL else ['dll'] 
     437        loaders = ['opencl', 'dll'] if use_opencl() else ['dll'] 
    437438        models = models[1:] 
    438439    else: 
    439         loaders = ['opencl', 'dll'] if core.HAVE_OPENCL else ['dll'] 
     440        loaders = ['opencl', 'dll'] if use_opencl() else ['dll'] 
    440441    if not models: 
    441442        print("""\ 
     
    466467    Run "nosetests sasmodels" on the command line to invoke it. 
    467468    """ 
    468     loaders = ['opencl', 'dll'] if core.HAVE_OPENCL else ['dll'] 
     469    loaders = ['opencl', 'dll'] if use_opencl() else ['dll'] 
    469470    tests = make_suite(loaders, ['all']) 
    470471    def build_test(test): 
     
    476477        # variable test will be shared amongst all the tests, and we will be 
    477478        # repeatedly testing vesicle. 
    478         return lambda name: test.run_all(), test.test_name 
     479 
     480        # Note: in sasview sas.sasgui.perspectives.fitting.gpu_options 
     481        # requires that the test.description field be set. 
     482        wrap = lambda: test.run_all() 
     483        wrap.description = test.test_name 
     484        return wrap 
     485        # The following would work with nosetests and pytest: 
     486        #     return lambda name: test.run_all(), test.test_name 
     487 
    479488    for test in tests: 
    480489        yield build_test(test) 
  • sasmodels/sasview_model.py

    ra69d8cd r3221de0  
    665665 
    666666    def _calculate_Iq(self, qx, qy=None): 
    667         #core.HAVE_OPENCL = False 
    668667        if self._model is None: 
    669668            self._model = core.build_model(self._model_info) 
Note: See TracChangeset for help on using the changeset viewer.