Пример #1
0
    def expansion(node: 'Allreduce', state: SDFGState, sdfg: SDFG, **kwargs):

        node.validate(sdfg, state)
        for edge in state.in_edges(node):
            if edge.dst_conn == '_inbuffer':
                input_edge = edge
        for edge in state.out_edges(node):
            if edge.src_conn == '_outbuffer':
                output_edge = edge

        input_dims = input_edge.data.subset.size_exact()
        output_dims = output_edge.data.subset.size_exact()
        input_data = sdfg.arrays[input_edge.data.data]
        output_data = sdfg.arrays[output_edge.data.data]

        # Verify that data is on the GPU
        if input_data.storage is not dtypes.StorageType.GPU_Global:
            raise ValueError('Input of NCCL Send must reside '
                             ' in global GPU memory.')
        if output_data.storage is not dtypes.StorageType.GPU_Global:
            raise ValueError('Output of NCCL Recv must reside '
                             ' in global GPU memory.')

        redtype = node.reduction_type

        redtype = nutil.NCCL_SUPPORTED_OPERATIONS[redtype]
        wcr_str = str(redtype)
        wcr_str = wcr_str[wcr_str.find('.') + 1:]  # Skip "NcclReductionType."

        nccl_dtype_str = nutil.Nccl_dtypes(input_data.dtype.base_type)
        count_str = "*".join(str(e) for e in input_dims)

        if input_data.dtype.veclen > 1:
            raise (NotImplementedError)

        code = f"""ncclAllReduce(_inbuffer, _outbuffer, {count_str}, {nccl_dtype_str}, {wcr_str},  __state->ncclCommunicators->at(__dace_cuda_device),  __dace_current_stream)"""

        if Config.get('compiler', 'build_type') == 'Debug':
            code = '''DACE_NCCL_CHECK(''' + code + ''');\n'''
        else:
            code = code + ''';\n'''

        if Config.get_bool('debugprint'):
            code = (
                f'''printf("{str(node)}: begin;  dev: %d\\n", __dace_cuda_device);\n'''
                + code +
                f'''printf("{str(node)}: end;  dev: %d\\n\\n", __dace_cuda_device);\n'''
            )

        code += """\ncudaStreamSynchronize(__dace_current_stream);"""

        tasklet = nodes.Tasklet(node.name + "_" + wcr_str,
                                node.in_connectors,
                                node.out_connectors,
                                code,
                                location=node.location,
                                language=dtypes.Language.CPP)
        return tasklet
Пример #2
0
    def expansion(node: 'Send', state: SDFGState, sdfg: SDFG, **kwargs):

        node.validate(sdfg, state)
        for edge in state.in_edges(node):
            if edge.dst_conn == '_inbuffer':
                input_edge = edge

        input_dims = input_edge.data.subset.size_exact()
        input_data = sdfg.arrays[input_edge.data.data]

        # Verify that data is on the GPU
        if input_data.storage is not dtypes.StorageType.GPU_Global:
            raise ValueError('Input of NCCL Send must reside '
                             ' in global GPU memory.')

        peer = node.peer
        peerstr = str(peer)
        for fs in peer.free_symbols:
            if fs.name in sdfg.arrays:
                sdfg.arrays[fs.name].lifetime = dtypes.AllocationLifetime.SDFG
            if fs.name in sdfg.parent_sdfg.arrays:
                sdfg.parent_sdfg.arrays[
                    fs.name].lifetime = dtypes.AllocationLifetime.SDFG

        nccl_dtype_str = nutil.Nccl_dtypes(input_data.dtype.base_type)
        count_str = "*".join(str(e) for e in input_dims)

        if input_data.dtype.veclen > 1:
            raise (NotImplementedError)

        code = f"""ncclSend(_inbuffer, {count_str}, {nccl_dtype_str}, {peerstr}, __state->ncclCommunicators->at(__dace_cuda_device),  __dace_current_stream)"""
        if Config.get('compiler', 'build_type') == 'Debug':
            code = '''DACE_NCCL_CHECK(''' + code + ''');\n'''

        else:
            code = code + ''';\n'''

        if Config.get_bool('debugprint'):
            code = (
                f'''printf("{str(node)}: begin;  dev,peer: %d, %d\\n", __dace_cuda_device, {peerstr});\n'''
                + code +
                f'''printf("{str(node)}: end;  dev,peer: %d, %d\\n\\n", __dace_cuda_device, {peerstr});\n'''
            )

        code = nutil.aggregate_calls(sdfg, state, node, code)

        tasklet = nodes.Tasklet(node.name,
                                node.in_connectors,
                                node.out_connectors,
                                code,
                                location=node.location,
                                language=dtypes.Language.CPP,
                                library_expansion_symbols=set(
                                    map(str, peer.free_symbols)))

        return tasklet
Пример #3
0
def tmp_location(name: str) -> str:
    """ Returns the absolute path to the temporary folder
        :param name: name of the SDFG
        :return: path to the tmp folder
    """
    build_folder = Config.get('default_build_folder')
    return os.path.abspath(os.path.join(build_folder, name, "map", "tmp.json"))
Пример #4
0
def create_cpp_map(code: str, name: str, target_name: str, build_folder: str,
                   sourceFiles: [str], made_with_api: bool):
    """ Creates the mapping from the SDFG nodes to the C++ code lines.
        The mapping gets saved at: <SDFG build folder>/map/map_cpp.json
        :param code: C++ code containing the identifiers '////__DACE:0:0:0'
        :param name: The name of the SDFG
        :param target_name: The target type, example: 'cpu'
        :param build_folder: The build_folder of the SDFG
        :param sourceFiles: A list of source files of to the SDFG
        :param made_with_api: true if the SDFG was created just with the API
    """
    codegen_debug = Config.get_bool('compiler', 'codegen_lineinfo')
    cpp_mapper = MapCpp(code, name, target_name)
    cpp_mapper.mapper(codegen_debug)

    folder = save("cpp", name, cpp_mapper.map, build_folder)

    if codegen_debug:
        save("codegen", name, cpp_mapper.codegen_map, build_folder)

    # Send information about the SDFG to VSCode
    send({
        "type": "registerFunction",
        "name": name,
        "path_cache": folder,
        "path_file": sourceFiles,
        "target_name": target_name,
        "made_with_api": made_with_api,
        "codegen_map": codegen_debug
    })
Пример #5
0
def create_py_map(sdfg):
    """ Creates the mapping from the python source lines to the SDFG nodes.
        The mapping gets saved at: <SDFG build folder>/map/map_py.json
        :param sdfg: The SDFG for which the mapping will be created
    """
    # If the cache setting is set to 'hash' then we don't create a
    # mapping as we don't know where to save it to due to
    # the hash value changing every time the state of the SDFG changes.
    if Config.get('cache') != 'hash':
        tmp = get_tmp(sdfg.name)
        py_mapper = MapPython(sdfg.name)
        py_mapper.mapper(sdfg, tmp)
        folder = sdfg.build_folder
        save("py", sdfg.name, py_mapper.map, folder)
        # If the SDFG was made with the API we need to create tmp info
        # as it doesn't have any
        sourceFiles = [src for src in get_src_files(sdfg, set())]
        # If tmp is None, then the SDFG was created with the API
        if tmp is None:
            temporaryInfo(
                sdfg.name, {
                    'build_folder': folder,
                    'src_files': sourceFiles,
                    'made_with_api': True,
                })
        else:
            tmp['src_files'] = sourceFiles
            temporaryInfo(sdfg.name, tmp)
Пример #6
0
def create_cpp_map(code: str, name: str, target_name: str):
    """ Creates the mapping from the SDFG nodes to the C++ code lines.
        The mapping gets saved at: <SDFG build folder>/map/map_cpp.json
        :param code: C++ code containing the identifiers '////__DACE:0:0:0'
        :param name: The name of the SDFG
        :param target_name: The target type, example: 'cpu'
    """
    tmp = get_tmp(name)
    if tmp is None:
        return
    remove_tmp(name, True)

    # If the cache setting is set to 'hash' then we don't create a
    # mapping as we don't know where to save it to due to
    # the hash value changing every time the state of the SDFG changes.
    # We send a message to the IDE in that case to notify the user of
    # restricted features.
    if Config.get('cache') != 'hash':
        codegen_debug = Config.get_bool('compiler', 'codegen_lineinfo')
        cpp_mapper = MapCpp(code, name, target_name)
        cpp_mapper.mapper(codegen_debug)

        folder = save("cpp", name, cpp_mapper.map, tmp.get("build_folder"))
        api = tmp.get('made_with_api')

        if codegen_debug:
            save("codegen", name, cpp_mapper.codegen_map,
                 tmp.get("build_folder"))

        # Send information about the SDFG to VSCode
        send({
            "type": "registerFunction",
            "name": name,
            "path_cache": folder,
            "path_file": tmp.get("src_files"),
            "target_name": target_name,
            "made_with_api": api if api else False,
            "codegen_map": codegen_debug
        })
    else:
        send({'type': 'restrictedFeatures', 'reason': 'config.cache.hash'})
Пример #7
0
def create_cache(name: str, folder: str) -> str:
    """ Creates the map folder in the build path if it
        does not yet exist
        :param name: name of the SDFG
        :param folder: the build folder
        :return: relative path to the created folder
    """
    if (folder is not None):
        create_folder(os.path.join(folder, "map"))
        return folder
    else:
        build_folder = Config.get('default_build_folder')
        cache_folder = os.path.join(build_folder, name)
        create_folder(os.path.join(cache_folder, "map"))
        return cache_folder
Пример #8
0
def remove_tmp(name: str, remove_cache: bool = False):
    """ Remove the tmp created by "temporaryInfo"
        :param name: name of the sdfg for which the tmp will be removed
        :param remove_cache: If true, checks if the directory only contains 
        the tmp file, if this is the case, remove the SDFG cache directory.
    """
    build_folder = Config.get('default_build_folder')
    path = os.path.join(build_folder, name)

    if not os.path.exists(path):
        return

    os.remove(os.path.join(path, 'map', 'tmp.json'))

    if (remove_cache and len(os.listdir(path)) == 1
            and len(os.listdir(os.path.join(path, 'map'))) == 0):
        if os.path.exists(path):
            os.rmdir(os.path.join(path, 'map'))
            os.rmdir(path)