Ejemplo n.º 1
0
def gen_unary_ops_tests(lf, rt, opts):
    for op_name, s0, s1 in bitwise_unary_ops:
        decls = check + limits + gen_random_val
        # {op}b
        content_src = bitwise_unary_test_template.format(
            op_name=op_name,
            lf=lf,
            rt=rt,
            includes=includes,
            decls=decls,
            rand_statement="__gen_random_val<{lf}, {rt}>();".format(lf=lf,
                                                                    rt=rt),
            test_statement=s0,
            l="",
            term="b")
        filename = get_filename(opts, op_name + "b", lf, rt)
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)

        # {op}l
        content_src = bitwise_unary_test_template.format(
            op_name=op_name,
            lf=lf,
            rt=rt,
            includes=includes,
            decls=decls,
            rand_statement="(raw_t)(rand() % 2);".format(lf=lf, rt=rt),
            test_statement=s1,
            l="l",
            term="l")
        filename = get_filename(opts, op_name + "l", lf, rt)
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)
Ejemplo n.º 2
0
def gen_modules_md(opts):
    common.myprint(opts, 'Generating modules.md')
    mods = common.get_modules(opts)
    ndms = []
    for mod in mods:
        name = eval('mods[mod].{}.hatch.name()'.format(mod))
        desc = eval('mods[mod].{}.hatch.desc()'.format(mod))
        ndms.append([name, desc, mod])
    filename = common.get_markdown_file(opts, 'modules')
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as fout:
        fout.write('''# Modules

NSIMD comes with several additional modules. A module provides a set of
functionnalities that are usually not at the same level as SIMD intrinsics
and/or that do not provide all C and C++ APIs. These functionnalities are
given with the library because they make heavy use of NSIMD core which
abstract SIMD intrinsics. Below is the exhaustive list of modules.

''')
        for ndm in ndms:
            fout.write('- [{}](module_{}_overview.md)  \n'.format(
                ndm[0], ndm[2]))
            fout.write('\n'.join(['  {}'.format(line.strip()) \
                                  for line in ndm[1].split('\n')]))
            fout.write('\n\n')
Ejemplo n.º 3
0
def doit(opts):
    common.myprint(opts, 'Generating friendly but not optimized advanced '
                   'C++ API')
    filename = os.path.join(opts.include_dir, 'friendly_but_not_optimized.hpp')
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as out:
        out.write('''#ifndef NSIMD_FRIENDLY_BUT_NOT_OPTIMIZED_HPP
                     #define NSIMD_FRIENDLY_BUT_NOT_OPTIMIZED_HPP

                     #include <nsimd/nsimd.h>
                     #include <nsimd/cxx_adv_api.hpp>

                     namespace nsimd {{

                     '''.format(year=date.today().year))
        for op_name, operator in operators.operators.items():
            if operator.cxx_operator == None or len(operator.params) != 3 or \
               operator.name in ['shl', 'shr']:
                continue
            out.write('''{hbar}

                         {code}

                         '''.format(hbar=common.hbar, code=get_impl(operator)))
        out.write('''{hbar}

                     }} // namespace nsimd

                     #endif'''.format(hbar=common.hbar))
    common.clang_format(opts, filename)
Ejemplo n.º 4
0
def doit(opts):
    print ('-- Generating base APIs')
    common.mkdir_p(opts.include_dir)
    filename = os.path.join(opts.include_dir, 'functions.h')
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(filename) as out:
        out.write('''#ifndef NSIMD_FUNCTIONS_H
                     #define NSIMD_FUNCTIONS_H

                     '''.format(year=date.today().year))

        for op_name, operator in operators.operators.items():
            out.write('''{}

                         #include NSIMD_AUTO_INCLUDE({}.h)

                         {}

                         {}

                         '''.format(common.hbar, operator.name,
                                    get_c_base_generic(operator),
                                    get_cxx_base_generic(operator)))

        out.write('''{hbar}

                     {put_decl}

                     {hbar}

                     #endif'''. \
                     format(hbar=common.hbar, put_decl=get_put_decl()))
    common.clang_format(opts, filename)
Ejemplo n.º 5
0
def doit(opts):
    print ('-- Generating advanced C++ API')
    filename = os.path.join(opts.include_dir, 'cxx_adv_api_functions.hpp')
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as out:
        out.write('''#ifndef NSIMD_CXX_ADV_API_FUNCTIONS_HPP
                     #define NSIMD_CXX_ADV_API_FUNCTIONS_HPP

                     namespace nsimd {{

                     '''.format(year=date.today().year))

        for op_name, operator in operators.operators.items():
            if not operator.autogen_cxx_adv:
                continue

            out.write('''{hbar}

                         {code}

                         '''.format(hbar=common.hbar,
                                    code=get_cxx_advanced_generic(operator)))


        out.write('''{hbar}

                     }} // namespace nsimd

                     #endif'''.format(hbar=common.hbar))
    common.clang_format(opts, filename)
Ejemplo n.º 6
0
def gen_archis_write_file(opts, op, platform, simd_ext, simd_dir):
    filename = os.path.join(simd_dir, '{}.h'.format(op.name))
    if not common.can_create_filename(opts, filename):
        return
    mod = opts.platforms[platform]
    with common.open_utf8(opts, filename) as out:
        out.write('''#ifndef {guard}
                     #define {guard}

                     #include <nsimd/{platform}/{simd_ext}/types.h>
                     {additional_include}

                     {code}

                     {hbar}

                     #endif
                     '''.format(additional_include=mod.get_additional_include(
            op.name, platform, simd_ext),
                                year=date.today().year,
                                guard=op.get_header_guard(platform, simd_ext),
                                platform=platform,
                                simd_ext=simd_ext,
                                func=op.name,
                                hbar=common.hbar,
                                code=get_simd_implementation(
                                    opts, op, mod, simd_ext)))
    common.clang_format(opts, filename)
Ejemplo n.º 7
0
def doit(opts):
    common.myprint(opts, 'Generating ulps')
    common.mkdir_p(opts.ulps_dir)
    for op_name, operator in operators.operators.items():
        if not operator.tests_mpfr:
            continue
        if op_name in ['gammaln', 'lgamma', 'pow']:
            continue

        mpfr_func = operator.tests_mpfr_name()
        mpfr_rnd = ", MPFR_RNDN"

        for typ in common.ftypes:
            if typ == 'f16':
                random_generator = random_f16_generator
                convert_to_type = "nsimd_f32_to_f16"
                convert_from_type = "nsimd_f16_to_f32"
                mantisse = 10
                size = 0xffff
                mpfr_suffix = "flt"
            elif typ == 'f32':
                convert_to_type = "(f32)"
                convert_from_type = ""
                random_generator = random_f32_generator
                mantisse = 23
                #size = 0xffffffff
                size = 0x00ffffff
                mpfr_suffix = "flt"
            elif typ == 'f64':
                convert_to_type = "(f64)"
                convert_from_type = ""
                random_generator = random_f64_generator
                mantisse = 52
                size = 0x00ffffff
                mpfr_suffix = "d"
            else:
                raise Exception('Unsupported type "{}"'.format(typ))

            filename = os.path.join(opts.ulps_dir, '{}_{}_{}.cpp'. \
                       format(op_name, "ulp", typ))

            if not common.can_create_filename(opts, filename):
                continue

            with common.open_utf8(opts, filename) as out:
                out.write(includes)
                out.write(gen_tests.relative_distance_cpp)
                out.write(
                    code.format(typ=typ,
                                nsimd_func=op_name,
                                mpfr_func=mpfr_func,
                                mpfr_rnd=mpfr_rnd,
                                random_generator=random_generator,
                                convert_from_type=convert_from_type,
                                convert_to_type=convert_to_type,
                                mantisse=mantisse,
                                SIZE=size,
                                mpfr_suffix=mpfr_suffix))

            common.clang_format(opts, filename)
Ejemplo n.º 8
0
def gen_bench(f, simd, typ):
    ## TODO
    path = gen_filename(f, simd, typ)
    ## Check if we need to create the file
    if not common.can_create_filename(_opts, path):
        return
    ## Generate specific code for the bench
    category = common.nsimd_category(simd)
    code = gen_code(f, simd, typ, category=category)
    if code is None:
        return
    ## Now aggregate every parts
    bench = ''
    #bench += gen_bench_asm_function(f, typ, category)
    bench += gen_bench_against(f, simd, typ, f.bench_against_cpu())
    bench += code
    bench += gen_bench_unrolls(f, simd, typ, category)
    bench += gen_bench_against(f, simd, typ, f.bench_against_libs())
    ## Finalize code
    code = gen_bench_from_code(f, typ, bench)
    ## Write file
    with common.open_utf8(path) as f:
        f.write(code)
    ## Clang-format it!
    common.clang_format(_opts, path)
Ejemplo n.º 9
0
def gen_doc(opts):
    for op in operators:
        filename = common.get_markdown_api_file(opts, op.name, 'fixed_point')
        with common.open_utf8(opts, filename) as fout:
            fout.write(
                api_template.format(full_name=op.full_name,
                                    desc=op.desc,
                                    decl=gen_decl(op)))
Ejemplo n.º 10
0
def gen_doc(opts):
    for op in operators:
        filename = os.path.join(opts.script_dir, '..', 'doc', 'markdown',
                                'modules', 'fixed_point',
                                'api_{}.md'.format(op.name))
        with common.open_utf8(opts, filename) as fout:
            fout.write(
                api_template.format(full_name=op.full_name,
                                    desc=op.desc,
                                    decl=gen_decl(op)))
Ejemplo n.º 11
0
def gen_doc(opts, op_list):
    for _, op in operators.operators.items():
        if op.name not in op_list:
            continue
        filename = common.get_markdown_api_file(opts, op.name, 'fixed_point')
        with common.open_utf8(opts, filename) as fout:
            fout.write(
                api_template.format(full_name=op.full_name,
                                    desc=op.desc,
                                    decl=gen_decl(op)))
Ejemplo n.º 12
0
def gen_if_else_tests(lf, rt, opts):
    decls = check + limits + comparison_fp + gen_random_val
    content_src = if_else_test_template.format(lf=lf,
                                               rt=rt,
                                               includes=includes,
                                               decls=decls)
    filename = get_filename(opts, "if_else", lf, rt)
    with common.open_utf8(opts, filename) as fp:
        fp.write(content_src)
    common.clang_format(opts, filename)
Ejemplo n.º 13
0
def gen_html(opts):
    # check if md2html exists
    md2html = 'md2html.exe' if platform.system() == 'Windows' else 'md2html'
    doc_dir = os.path.join(opts.script_dir, '..', 'doc')
    full_path_md2html = os.path.join(doc_dir, md2html)
    if not os.path.isfile(full_path_md2html):
        msg = '-- Cannot generate HTML: {} not found. '.format(md2html)
        if platform.system() == 'Windows':
            msg += 'Run "nmake /F Makefile.win" in {}'.format(doc_dir)
        else:
            msg += 'Run "make -f Makefile.nix" in {}'.format(doc_dir)
        print(msg)
        return

    # get all markdown files
    md_dir = os.path.join(doc_dir, 'markdown/modules/fixed_point')
    html_dir = os.path.join(doc_dir, 'html/modules/fixed_point')
    common.mkdir_p(html_dir)
    dirs = [md_dir]
    md_files = []
    while len(dirs) > 0:
        curr_dir = dirs.pop()
        entries = os.listdir(curr_dir)
        for entry in entries:
            full_path_entry = os.path.join(curr_dir, entry)
            if full_path_entry == '..' or full_path_entry == '.':
                continue
            elif os.path.isdir(full_path_entry):
                continue
            elif entry.endswith('.md'):
                md_files.append(full_path_entry)

    # header and footer
    doc_title = '`nsimd` fixed point module documentation'
    root_dir = '../..'
    assets_dir = '../../assets'
    img_dir = '../../img'
    header = header_src.format(doc_title=doc_title,
                               root_dir=root_dir,
                               img_dir=img_dir,
                               assets_dir=assets_dir)
    footer = footer_src
    tmp_file = os.path.join(doc_dir, 'tmp.html')
    for filename in md_files:
        i = filename.rfind('markdown')
        if i == -1:
            continue
        output = filename[0:i] + 'html' + filename[i + 8:-2] + 'html'
        common.mkdir_p(os.path.dirname(output))
        os.system('{} "{}" "{}"'.format(full_path_md2html, filename, tmp_file))
        with common.open_utf8(opts, output) as fout:
            fout.write(header)
            with io.open(tmp_file, mode='r', encoding='utf-8') as fin:
                fout.write(fin.read())
            fout.write(footer)
Ejemplo n.º 14
0
def gen_comparison_tests(lf, rt, opts):
    for op_name, op_val in comparison_ops:
        decls = check + limits + comparison_log.format(op_val=op_val) + gen_random_val
        content_src = comparison_test_template.format(
            op_name=op_name, op_val=op_val, lf=lf, rt=rt,
            includes=includes, decls=decls)
        filename = get_filename(opts, op_name, lf, rt)
        if filename == None:
            continue
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)
Ejemplo n.º 15
0
def gen_minmax_ops_tests(lf, rt, opts):
    for op_name in minmax_ops:
        decls = check + limits + comparison_fp + gen_random_val
        content_src = minmax_test_template.format(op_name=op_name,
                                                  lf=lf,
                                                  rt=rt,
                                                  includes=includes,
                                                  decls=decls)
        filename = get_filename(opts, op_name, lf, rt)
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)
Ejemplo n.º 16
0
def gen_ternary_ops_tests(lf, rt, opts):
    for op_name, statement in ternary_ops:
        decls = check + limits + comparison_fp + gen_random_val
        content_src = ternary_ops_template.format(
            op_name=op_name, check_statement=statement.format(lf=lf, rt=rt),
            lf=lf, rt=rt,includes=includes, decls=decls)
        filename = get_filename(opts, op_name, lf, rt)
        if filename == None:
            continue
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)
Ejemplo n.º 17
0
def write_cpp(opts, simd_ext, emulate_fp16):
    filename = os.path.join(opts.src_dir, 'api_{}.cpp'.format(simd_ext))
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as out:
        out.write('''#define NSIMD_INSIDE
                     #include <nsimd/nsimd.h>
                     #include <nsimd/cxx_adv_api.hpp>

                     '''.format(year=date.today().year))
        out.write(get_put_impl(simd_ext))
    common.clang_format(opts, filename)
Ejemplo n.º 18
0
def gen_math_functions_tests(lf, rt, opts):
    for op_name in math_ops:
        decls = check + limits + comparison_fp + gen_random_val
        if op_name == "rec": decls += rec_reference
        content_src = math_test_template.format(op_name=op_name,
                                                lf=lf,
                                                rt=rt,
                                                includes=includes,
                                                decls=decls)
        filename = get_filename(opts, op_name, lf, rt)
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)
Ejemplo n.º 19
0
def gen_archis_write_put(opts, platform, simd_ext, simd_dir):
    filename = os.path.join(simd_dir, 'put.h')
    if not common.can_create_filename(opts, filename):
        return
    op = None
    with common.open_utf8(filename) as out:
        out.write( \
        '''#ifndef NSIMD_{PLATFORM}_{SIMD_EXT}_PUT_H
           #define NSIMD_{PLATFORM}_{SIMD_EXT}_PUT_H

           {include_cpu_put}#include <nsimd/{platform}/{simd_ext}/types.h>
           #include <stdio.h>

           {hbar}

           '''.format(year=date.today().year, hbar=common.hbar,
                      simd_ext=simd_ext, platform=platform,
                      PLATFORM=platform.upper(), SIMD_EXT=simd_ext.upper(),
                      include_cpu_put='#include <nsimd/cpu/cpu/put.h>\n' \
                      if simd_ext != 'cpu' else ''))
        for typ in common.types:
            out.write( \
            '''#if NSIMD_CXX > 0
               extern "C" {{
               #endif

               NSIMD_DLLSPEC
               int nsimd_put_{simd_ext}_{typ}(FILE *, const char *,
                                              nsimd_{simd_ext}_v{typ});

               #if NSIMD_CXX > 0
               }} // extern "C"
               #endif

               #if NSIMD_CXX > 0
               namespace nsimd {{
               NSIMD_INLINE int put(FILE *out, const char *fmt,
                                    nsimd_{simd_ext}_v{typ} a0, {typ},
                                    {simd_ext}) {{
                 return nsimd_put_{simd_ext}_{typ}(out, fmt, a0);
               }}
               }} // namespace nsimd
               #endif

               {hbar}

               '''.format(simd_ext=simd_ext, hbar=common.hbar, typ=typ))
        out.write('#endif')
    common.clang_format(opts, filename)
Ejemplo n.º 20
0
def gen_api(opts):
    filename = os.path.join(opts.script_dir, '..', 'doc', 'markdown',
                            'modules', 'fixed_point', 'api.md')
    with common.open_utf8(opts, filename) as fout:
        fout.write('''# NSIMD fixed point API\n''')
        for cat in fp_categories:
            ops = [op for op in fp_operators if cat in op.categories]
            if (len(ops) == 0):
                continue

            fout.write('\n## {}\n\n'.format(cat))

            for op in ops:
                fout.write('- [{full_name} ({op_name})](api_{op_name}.md)\n'\
                           .format(full_name=op.full_name, op_name=op.name))
Ejemplo n.º 21
0
Archivo: hatch.py Proyecto: zoq/nsimd
def gen_doc_api(opts):
    filename = common.get_markdown_file(opts, 'api', 'spmd')
    if not common.can_create_filename(opts, filename):
        return

    # Build tree for api.md
    api = dict()
    for _, operator in operators.operators.items():
        if not operator.has_scalar_impl:
            continue
        for c in operator.categories:
            if c not in api:
                api[c] = [operator]
            else:
                api[c].append(operator)

    with common.open_utf8(opts, filename) as fout:
        fout.write(
'''# NSIMD SPMD API reference

This page contains the exhaustive API of the SPMD module. Note that most
operators names follow the simple naming `k_[NSIMD name]` and have the same
semantics. This page is light, you may use CTRL+F to find the operator you
are looking for.

For genericity on the base type you should use operator names instead of
infix operators, e.g. `k_add` instead of `+`. Indeed for `f16`'s NVIDIA CUDA
and NSIMD do not provide overloads and therefore code using `+` will fail to
compile.

Note that all operators accept literals and scalars. For example you may
write `k_add(a, 1)` or `float s; k_add(a, s);`. This also applies when
using infix operators. But note that literals or scalars must have the
same type as the other operands.

''')

        for c, ops in api.items():
            if len(ops) == 0:
                continue
            fout.write('\n## {}\n\n'.format(c.title))
            for op in ops:
                fout.write('- `{}`  \n'.format(get_signature(op)))
                if op.cxx_operator != None:
                    fout.write('  Infix operator: `{}` ' \
                               '(*for certain types only*)  \n'.\
                               format(op.cxx_operator))
                fout.write('  {}\n\n'.format(op.desc))
Ejemplo n.º 22
0
def gen_tests(opts):
    for func in rand_functions:
        for word_size, nwords_nrounds in func.wordsize_nwords_nrounds.items():
            for nwords, list_nrounds in nwords_nrounds.items():
                for nrounds in list_nrounds:
                    # Write headers
                    dirname = os.path.join(opts.tests_dir, 'modules', 'random')
                    common.mkdir_p(dirname)
                    filename = os.path.join(dirname, '{}.cpp'. \
                               format(func.gen_function_name(nwords, word_size,
                                                             nrounds)))
                    with common.open_utf8(opts, filename) as out:
                        out.write(
                            func.gen_tests(opts, nrounds, word_size, nwords))

                    common.clang_format(opts, filename)
Ejemplo n.º 23
0
def gen_api(opts):
    filename = common.get_markdown_file(opts, 'api', 'fixed_point')
    with common.open_utf8(opts, filename) as fout:
        fout.write('''# NSIMD fixed point API\n''')
        for cat in fp_categories:
            ops = [op for op in fp_operators if cat in op.categories]
            if (len(ops) == 0):
                continue

            fout.write('\n## {}\n\n'.format(cat))

            for op in ops:
                fout.write(
                    '- [{} ({})](module_fixed_point_api_{}.md)\n'\
                           .format(op.full_name, op.name,
                                   common.to_filename(op.name)))
Ejemplo n.º 24
0
def gen_math_functions_tests(lf, rt, opts):
    for op_name in math_ops:
        decls = check + limits + comparison_fp + gen_random_val
        if op_name == "rec":
            decls += rec_reference
            ref_op_name = 'rec'
        else:
            ref_op_name = 'nsimd_scalar_abs_f64'
        content_src = math_test_template.format(op_name=op_name, lf=lf, rt=rt,
                                                ref_op_name=ref_op_name,
                                                includes=includes, decls=decls)
        filename = get_filename(opts, op_name, lf, rt)
        if filename == None:
            continue
        with common.open_utf8(opts, filename) as fp:
            fp.write(content_src)
        common.clang_format(opts, filename)
Ejemplo n.º 25
0
def gen_doc_html(opts, title):
    if not opts.list_files:
        build_exe_for_doc(opts)
        md2html = 'md2html.exe' if platform.system() == 'Windows' \
                                else 'md2html'
        doc_dir = os.path.join(opts.script_dir, '..', 'doc')
        full_path_md2html = os.path.join(doc_dir, md2html)
        if not os.path.isfile(full_path_md2html):
            common.myprint(opts, '{} not found'.format(md2html))
            return

    # get all markdown files
    md_dir = common.get_markdown_dir(opts)
    html_dir = get_html_dir(opts)

    if not os.path.isdir(html_dir):
        mkdir_p(html_dir)

    doc_files = []
    for filename in os.listdir(md_dir):
        name = os.path.basename(filename)
        if name.endswith('.md'):
            doc_files.append(os.path.splitext(name)[0])

    if opts.list_files:
        ## list gen files
        for filename in doc_files:
            input_name = os.path.join(md_dir, filename + '.md')
            output_name = os.path.join(html_dir, filename + '.html')
            print(output_name)
    else:
        ## gen html files
        footer = get_html_footer()
        tmp_file = os.path.join(doc_dir, 'tmp.html')
        for filename in doc_files:
            header = get_html_header(opts, title, filename)
            input_name = os.path.join(md_dir, filename + '.md')
            output_name = os.path.join(html_dir, filename + '.html')
            os.system('{} "{}" "{}"'.format(full_path_md2html, input_name,
                                            tmp_file))
            with common.open_utf8(opts, output_name) as fout:
                fout.write(header)
                with io.open(tmp_file, mode='r', encoding='utf-8') as fin:
                    fout.write(fin.read())
                fout.write(footer)
Ejemplo n.º 26
0
def write_cpp(opts, simd_ext, emulate_fp16):
    filename = os.path.join(opts.src_dir, 'api_{}.cpp'.format(simd_ext))
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as out:
        out.write('''#define NSIMD_INSIDE
                     #include <nsimd/nsimd.h>
                     #include <nsimd/cxx_adv_api.hpp>

                     '''.format(year=date.today().year))
        for op_name, operator in operators.operators.items():
            if operator.src:
                out.write('''{hbar}

                             #include <nsimd/src/{name}.hpp>

                             '''.format(name=operator.name, hbar=common.hbar))
                out.write(get_impl(operator, emulate_fp16, simd_ext))
        out.write(get_put_impl(simd_ext))

    common.clang_format(opts, filename)
Ejemplo n.º 27
0
def gen_api(opts, op_list):
    api = dict()
    for _, operator in operators.operators.items():
        if operator.name not in op_list:
            continue
        for c in operator.categories:
            if c not in api:
                api[c] = [operator]
            else:
                api[c].append(operator)

    filename = common.get_markdown_file(opts, 'api', 'fixed_point')
    with common.open_utf8(opts, filename) as fout:
        fout.write('''# NSIMD fixed point API\n''')
        for c, ops in api.items():
            if len(ops) == 0:
                continue
            fout.write('\n## {}\n\n'.format(c.title))
            for op in ops:
                fout.write('- [{} ({})](module_fixed_point_api_{}.md)\n'. \
                           format(op.full_name, op.name,
                                  common.to_filename(op.name)))
Ejemplo n.º 28
0
def gen_doc(opts):
    api = ''
    for func in rand_functions:
        for word_size, nwords_nrounds in func.wordsize_nwords_nrounds.items():
            for nwords, list_nrounds in nwords_nrounds.items():
                for nrounds in list_nrounds:
                    api += '- `' + func.gen_signature(nwords, word_size,
                                                      nrounds) + '`;  \n'
                    api += '  Returns a random number using the ' \
                           '{func_name} generator\n\n'. \
                           format(func_name=func.name)

    res = '''
# NSIMD Random module overview

{desc}

Two different algorithms are proposed : threefry and philox. Both should give
high quality random number.
Threefry is quicker on CPU, while philox is best used on GPU.

Both algorithms are counter based pseudorandom number generator, meaning that
they need two parameters:
- a key, each key will generate an unique sequence,
- a counter, which will give the different numbers in the sequence.

# NSIMD Random API reference

{api}
'''.format(desc=desc(), api=api)

    filename = common.get_markdown_file(opts, 'overview', 'random')
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as fout:
        fout.write(res)
Ejemplo n.º 29
0
def doit(opts):
    common.myprint(opts, 'Generating advanced C++ API')
    filename = os.path.join(opts.include_dir, 'cxx_adv_api_functions.hpp')
    if not common.can_create_filename(opts, filename):
        return
    with common.open_utf8(opts, filename) as out:
        out.write('''#ifndef NSIMD_CXX_ADV_API_FUNCTIONS_HPP
                     #define NSIMD_CXX_ADV_API_FUNCTIONS_HPP

                     namespace nsimd {

                     ''')

        for op_name, operator in operators.operators.items():
            if not operator.autogen_cxx_adv:
                continue

            out.write('''{hbar}

                         {code}

                         '''.format(hbar=common.hbar,
                                    code=get_cxx_advanced_generic(operator)))

            if operator.cxx_operator and \
                (operator.args in [['v', 'v'], ['v', 'p']]):
                out.write('{hbar}\n{code}'. \
                        format(hbar=common.hbar,
                               code=gen_assignment_operators(operator)))

        out.write('''{hbar}

                     }} // namespace nsimd

                     #endif'''.format(hbar=common.hbar))
    common.clang_format(opts, filename)
Ejemplo n.º 30
0
def gen_bench(f, simd, typ):
    ## TODO
    path = gen_filename(f, simd, typ)
    ## Check if we need to create the file
    if not common.can_create_filename(_opts, path):
        return
    ## Generate specific code for the bench
    category = common.nsimd_category(simd)
    code = gen_code(f, simd, typ, category=category)
    if code is None:
        return
    ## Now aggregate every parts
    bench = ''
    #bench += gen_bench_asm_function(f, typ, category)
    bench += gen_bench_against(f, 'cpu', typ, f.bench_against_cpu())
    bench += code
    bench += gen_bench_unrolls(f, simd, typ, category)
    bench += gen_bench_against(f, simd, typ, f.bench_against_libs())
    ## bench_with_timestamp
    bench_with_timestamp = ''
    bench_with_timestamp += 'std::map<std::string, std::pair<' + typ + ', double>> sums;' + '\n'
    bench_with_timestamp += 'size_t const nb_runs = 10 * 1000;' + '\n'
    bench_with_timestamp += gen_bench_against_with_timestamp(
        f, 'cpu', typ, f.bench_against_cpu())
    bench_with_timestamp += gen_bench_with_timestamp(f, simd, typ, category)
    bench_with_timestamp += gen_bench_unrolls_with_timestamp(
        f, simd, typ, category)
    bench_with_timestamp += gen_bench_against_with_timestamp(
        f, simd, typ, f.bench_against_libs())
    bench_with_timestamp += '''
                            std::string json = "";
                            json += "{{\\n";
                            json += "  \\"benchmarks\\": [\\n";

                            for (auto const & bench_name_sum_time : sums) {{
                              std::string const & bench_name = bench_name_sum_time.first;
                              {typ} const & sum = bench_name_sum_time.second.first;
                              double const & elapsed_time_ns = bench_name_sum_time.second.second;

                              json += "  {{" "\\n";
                              json += "    \\"name\\": \\"" + bench_name + "/{typ}\\"," + "\\n";
                              json += "    \\"real_time\\": " + std::to_string(elapsed_time_ns) + "," + "\\n";
                              json += "    \\"sum\\": " + std::string(std::isfinite(sum) ? "" : "\\"") + std::to_string(sum) + std::string(std::isfinite(sum) ? "" : "\\"") + "," + "\\n";
                              json += "    \\"time_unit\\": \\"ns\\"\\n";
                              json += "  }}";
                              if (&bench_name_sum_time != &*sums.rbegin()) {{
                                json += ",";
                              }}
                              json += "\\n";
                            }}

                            json += "  ]\\n";
                            json += "}}\\n";

                            std::cout << json << std::flush;
                            '''.format(typ=typ)
    ## Finalize code
    code = gen_bench_from_code(f, typ, bench, '')  # bench_with_timestamp
    ## Write file
    with common.open_utf8(path) as f:
        f.write(code)
    ## Clang-format it!
    common.clang_format(_opts, path)