GitOrigin-RevId: bd964ed505
tags/v1.7.0
| @@ -1,84 +0,0 @@ | |||
| # This code is licensed under the MIT License. See the FindBANG.cmake script | |||
| # for the text of the license. | |||
| # The MIT License | |||
| # | |||
| # License for the specific language governing rights and limitations under | |||
| # Permission is hereby granted, free of charge, to any person obtaining a | |||
| # copy of this software and associated documentation files (the "Software"), | |||
| # to deal in the Software without restriction, including without limitation | |||
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| # and/or sell copies of the Software, and to permit persons to whom the | |||
| # Software is furnished to do so, subject to the following conditions: | |||
| # | |||
| # The above copyright notice and this permission notice shall be included | |||
| # in all copies or substantial portions of the Software. | |||
| # | |||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| # DEALINGS IN THE SOFTWARE. | |||
| # | |||
| ####################################################################### | |||
| # This converts a file written in makefile syntax into one that can be included | |||
| # by CMake. | |||
| file(READ ${input_file} depend_text) | |||
| if (NOT "${depend_text}" STREQUAL "") | |||
| # message("FOUND DEPENDS") | |||
| string(REPLACE "\\ " " " depend_text ${depend_text}) | |||
| # This works for the cncc -M generated dependency files. | |||
| string(REGEX REPLACE "^.* : " "" depend_text ${depend_text}) | |||
| string(REGEX REPLACE "[ \\\\]*\n" ";" depend_text ${depend_text}) | |||
| set(dependency_list "") | |||
| foreach(file ${depend_text}) | |||
| string(REGEX REPLACE "^ +" "" file ${file}) | |||
| # OK, now if we had a UNC path, cncc has a tendency to only output the first '/' | |||
| # instead of '//'. Here we will test to see if the file exists, if it doesn't then | |||
| # try to prepend another '/' to the path and test again. If it still fails remove the | |||
| # path. | |||
| if(NOT EXISTS "${file}") | |||
| if (EXISTS "/${file}") | |||
| set(file "/${file}") | |||
| else() | |||
| message(WARNING " Removing non-existent dependency file: ${file}") | |||
| set(file "") | |||
| endif() | |||
| endif() | |||
| if(NOT IS_DIRECTORY "${file}") | |||
| # If softlinks start to matter, we should change this to REALPATH. For now we need | |||
| # to flatten paths, because cncc can generate stuff like /bin/../include instead of | |||
| # just /include. | |||
| get_filename_component(file_absolute "${file}" ABSOLUTE) | |||
| list(APPEND dependency_list "${file_absolute}") | |||
| endif() | |||
| endforeach() | |||
| else() | |||
| # message("FOUND NO DEPENDS") | |||
| endif() | |||
| # Remove the duplicate entries and sort them. | |||
| list(REMOVE_DUPLICATES dependency_list) | |||
| list(SORT dependency_list) | |||
| foreach(file ${dependency_list}) | |||
| set(bang_cncc_depend "${bang_cncc_depend} \"${file}\"\n") | |||
| endforeach() | |||
| file(WRITE ${output_file} "# Generated by: make2cmake.cmake\nSET(BANG_CNCC_DEPEND\n ${bang_cncc_depend})\n\n") | |||
| @@ -1,103 +0,0 @@ | |||
| # This code is licensed under the MIT License. See the FindBANG.cmake script | |||
| # for the text of the license. | |||
| # The MIT License | |||
| # | |||
| # License for the specific language governing rights and limitations under | |||
| # Permission is hereby granted, free of charge, to any person obtaining a | |||
| # copy of this software and associated documentation files (the "Software"), | |||
| # to deal in the Software without restriction, including without limitation | |||
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| # and/or sell copies of the Software, and to permit persons to whom the | |||
| # Software is furnished to do so, subject to the following conditions: | |||
| # | |||
| # The above copyright notice and this permission notice shall be included | |||
| # in all copies or substantial portions of the Software. | |||
| # | |||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| # DEALINGS IN THE SOFTWARE. | |||
| # | |||
| ####################################################################### | |||
| # Parses a .cnbin file produced by cncc and reports statistics about the file. | |||
| file(READ ${input_file} file_text) | |||
| if (NOT "${file_text}" STREQUAL "") | |||
| string(REPLACE ";" "\\;" file_text ${file_text}) | |||
| string(REPLACE "\ncode" ";code" file_text ${file_text}) | |||
| list(LENGTH file_text len) | |||
| foreach(line ${file_text}) | |||
| # Only look at "code { }" blocks. | |||
| if(line MATCHES "^code") | |||
| # Break into individual lines. | |||
| string(REGEX REPLACE "\n" ";" line ${line}) | |||
| foreach(entry ${line}) | |||
| # Extract kernel names. | |||
| if (${entry} MATCHES "[^g]name = ([^ ]+)") | |||
| set(entry "${CMAKE_MATCH_1}") | |||
| # Check to see if the kernel name starts with "_" | |||
| set(skip FALSE) | |||
| # if (${entry} MATCHES "^_") | |||
| # Skip the rest of this block. | |||
| # message("Skipping ${entry}") | |||
| # set(skip TRUE) | |||
| # else () | |||
| message("Kernel: ${entry}") | |||
| # endif () | |||
| endif() | |||
| # Skip the rest of the block if necessary | |||
| if(NOT skip) | |||
| # Registers | |||
| if (${entry} MATCHES "reg([ ]+)=([ ]+)([^ ]+)") | |||
| set(entry "${CMAKE_MATCH_3}") | |||
| message("Registers: ${entry}") | |||
| endif() | |||
| # Local memory | |||
| if (${entry} MATCHES "lmem([ ]+)=([ ]+)([^ ]+)") | |||
| set(entry "${CMAKE_MATCH_3}") | |||
| message("Local: ${entry}") | |||
| endif() | |||
| # Shared memory | |||
| if (${entry} MATCHES "smem([ ]+)=([ ]+)([^ ]+)") | |||
| set(entry "${CMAKE_MATCH_3}") | |||
| message("Shared: ${entry}") | |||
| endif() | |||
| if (${entry} MATCHES "^}") | |||
| message("") | |||
| endif() | |||
| endif() | |||
| endforeach() | |||
| endif() | |||
| endforeach() | |||
| else() | |||
| # message("FOUND NO DEPENDS") | |||
| endif() | |||
| @@ -1,200 +0,0 @@ | |||
| # This code is licensed under the MIT License. See the FindBANG.cmake script | |||
| # for the text of the license. | |||
| # The MIT License | |||
| # | |||
| # License for the specific language governing rights and limitations under | |||
| # Permission is hereby granted, free of charge, to any person obtaining a | |||
| # copy of this software and associated documentation files (the "Software"), | |||
| # to deal in the Software without restriction, including without limitation | |||
| # the rights to use, copy, modify, merge, publish, distribute, sublicense, | |||
| # and/or sell copies of the Software, and to permit persons to whom the | |||
| # Software is furnished to do so, subject to the following conditions: | |||
| # | |||
| # The above copyright notice and this permission notice shall be included | |||
| # in all copies or substantial portions of the Software. | |||
| # | |||
| # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS | |||
| # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |||
| # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||
| # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | |||
| # DEALINGS IN THE SOFTWARE. | |||
| ########################################################################## | |||
| # This file runs the cncc commands to produce the desired output file along with | |||
| # the dependency file needed by CMake to compute dependencies. In addition the | |||
| # file checks the output of each command and if the command fails it deletes the | |||
| # output files. | |||
| # Input variables | |||
| # | |||
| # verbose:BOOL=<> OFF: Be as quiet as possible (default) | |||
| # ON : Describe each step | |||
| # | |||
| # build_configuration:STRING=<> Typically one of Debug, MinSizeRel, Release, or | |||
| # RelWithDebInfo, but it should match one of the | |||
| # entries in BANG_HOST_FLAGS. This is the build | |||
| # configuration used when compiling the code. If | |||
| # blank or unspecified Debug is assumed as this is | |||
| # what CMake does. | |||
| # | |||
| # generated_file:STRING=<> File to generate. This argument must be passed in. | |||
| # | |||
| # generated_cnbin_file:STRING=<> File to generate. This argument must be passed | |||
| # in if build_cnbin is true. | |||
| if(NOT generated_file) | |||
| message(FATAL_ERROR "You must specify generated_file on the command line") | |||
| endif() | |||
| # Set these up as variables to make reading the generated file easier | |||
| set(CMAKE_COMMAND "@CMAKE_COMMAND@") # path | |||
| set(source_file "@source_file@") # path | |||
| set(CNCC_generated_dependency_file "@CNCC_generated_dependency_file@") # path | |||
| set(cmake_dependency_file "@cmake_dependency_file@") # path | |||
| set(BANG_make2cmake "@BANG_make2cmake@") # path | |||
| set(BANG_parse_cnbin "@BANG_parse_cnbin@") # path | |||
| set(build_cnbin @build_cnbin@) # bool | |||
| set(BANG_HOST_COMPILER "@BANG_HOST_COMPILER@") # path | |||
| # We won't actually use these variables for now, but we need to set this, in | |||
| # order to force this file to be run again if it changes. | |||
| set(generated_file_path "@generated_file_path@") # path | |||
| set(generated_file_internal "@generated_file@") # path | |||
| set(generated_cnbin_file_internal "@generated_cnbin_file@") # path | |||
| set(BANG_CNCC_EXECUTABLE "@BANG_CNCC_EXECUTABLE@") # path | |||
| set(BANG_CNCC_FLAGS @BANG_CNCC_FLAGS@ ;; @BANG_WRAP_OPTION_CNCC_FLAGS@) # list | |||
| @BANG_CNCC_FLAGS_CONFIG@ | |||
| set(cncc_flags @cncc_flags@) # list | |||
| set(BANG_CNCC_INCLUDE_ARGS "@BANG_CNCC_INCLUDE_ARGS@") # list (needs to be in quotes to handle spaces properly). | |||
| set(format_flag "@format_flag@") # string | |||
| set(bang_language_flag @bang_language_flag@) # list | |||
| if(build_cnbin AND NOT generated_cnbin_file) | |||
| message(FATAL_ERROR "You must specify generated_cnbin_file on the command line") | |||
| endif() | |||
| # This is the list of host compilation flags. It C or CXX should already have | |||
| # been chosen by FindBANG.cmake. | |||
| @BANG_HOST_FLAGS@ | |||
| # Take the compiler flags and package them up to be sent to the compiler via -Xcompiler | |||
| set(cncc_host_compiler_flags "") | |||
| # If we weren't given a build_configuration, use Debug. | |||
| if(NOT build_configuration) | |||
| set(build_configuration Debug) | |||
| endif() | |||
| string(TOUPPER "${build_configuration}" build_configuration) | |||
| #message("BANG_CNCC_HOST_COMPILER_FLAGS = ${BANG_CNCC_HOST_COMPILER_FLAGS}") | |||
| foreach(flag ${CMAKE_HOST_FLAGS} ${CMAKE_HOST_FLAGS_${build_configuration}}) | |||
| # Extra quotes are added around each flag to help cncc parse out flags with spaces. | |||
| set(cncc_host_compiler_flags ${cncc_host_compiler_flags} ${flag}) | |||
| endforeach() | |||
| # message("cncc_host_compiler_flags = ${cncc_host_compiler_flags}") | |||
| # Add the build specific configuration flags | |||
| list(APPEND BANG_CNCC_FLAGS ${BANG_CNCC_FLAGS_${build_configuration}}) | |||
| # Remove the duplicated flags and including | |||
| list(REMOVE_DUPLICATES BANG_CNCC_FLAGS) | |||
| list(REMOVE_DUPLICATES BANG_CNCC_INCLUDE_ARGS) | |||
| # bang_execute_process - Executes a command with optional command echo and status message. | |||
| # | |||
| # status - Status message to print if verbose is true | |||
| # command - COMMAND argument from the usual execute_process argument structure | |||
| # ARGN - Remaining arguments are the command with arguments | |||
| # | |||
| # BANG_result - return value from running the command | |||
| # | |||
| # Make this a macro instead of a function, so that things like RESULT_VARIABLE | |||
| # and other return variables are present after executing the process. | |||
| macro(bang_execute_process status command) | |||
| set(_command ${command}) | |||
| if(NOT "x${_command}" STREQUAL "xCOMMAND") | |||
| message(FATAL_ERROR "Malformed call to bang_execute_process. Missing COMMAND as second argument. (command = ${command})") | |||
| endif() | |||
| if(verbose) | |||
| execute_process(COMMAND "${CMAKE_COMMAND}" -E echo -- ${status}) | |||
| # Now we need to build up our command string. We are accounting for quotes | |||
| # and spaces, anything else is left up to the user to fix if they want to | |||
| # copy and paste a runnable command line. | |||
| set(bang_execute_process_string) | |||
| foreach(arg ${ARGN}) | |||
| # If there are quotes, excape them, so they come through. | |||
| string(REPLACE "\"" "\\\"" arg ${arg}) | |||
| # Args with spaces need quotes around them to get them to be parsed as a single argument. | |||
| if(arg MATCHES " ") | |||
| list(APPEND bang_execute_process_string "\"${arg}\"") | |||
| else() | |||
| list(APPEND bang_execute_process_string ${arg}) | |||
| endif() | |||
| endforeach() | |||
| # Echo the command | |||
| execute_process(COMMAND ${CMAKE_COMMAND} -E echo ${bang_execute_process_string}) | |||
| endif() | |||
| # Run the command | |||
| execute_process(COMMAND ${ARGN} RESULT_VARIABLE BANG_result ) | |||
| endmacro() | |||
| # Delete the target file | |||
| bang_execute_process( | |||
| "Removing ${generated_file}" | |||
| COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}" | |||
| ) | |||
| # cncc ignore host flags | |||
| set(cncc_host_compiler_flags "") | |||
| # Generate the code | |||
| bang_execute_process( | |||
| "Generating ${generated_file}" | |||
| COMMAND "${BANG_CNCC_EXECUTABLE}" | |||
| "${source_file}" | |||
| ${bang_language_flag} | |||
| ${format_flag} -o "${generated_file}" | |||
| ${cncc_flags} | |||
| ${cncc_host_compiler_flags} | |||
| ${BANG_CNCC_FLAGS} | |||
| -DCNCC | |||
| ${BANG_CNCC_INCLUDE_ARGS} | |||
| ) | |||
| if(BANG_result) | |||
| # Since cncc can sometimes leave half done files make sure that we delete the output file. | |||
| bang_execute_process( | |||
| "Removing ${generated_file}" | |||
| COMMAND "${CMAKE_COMMAND}" -E remove "${generated_file}" | |||
| ) | |||
| message(FATAL_ERROR "Error generating file ${generated_file}") | |||
| else() | |||
| message(VERBOSE "Generated ${generated_file} successfully.") | |||
| endif() | |||
| # Cnbin resource report commands. | |||
| if( build_cnbin ) | |||
| # Run with -cnbin to produce resource usage report. | |||
| bang_execute_process( | |||
| "Generating ${generated_cnbin_file}" | |||
| COMMAND "${BANG_CNCC_EXECUTABLE}" | |||
| "${source_file}" | |||
| ${BANG_CNCC_FLAGS} | |||
| ${cncc_flags} | |||
| ${cncc_host_compiler_flags} | |||
| -DCNCC | |||
| -cnbin | |||
| -o "${generated_cnbin_file}" | |||
| ${BANG_CNCC_INCLUDE_ARGS} | |||
| ) | |||
| # Execute the parser script. | |||
| bang_execute_process( | |||
| "Executing the parser script" | |||
| COMMAND "${CMAKE_COMMAND}" | |||
| -D "input_file:STRING=${generated_cnbin_file}" | |||
| -P "${BANG_parse_cnbin}" | |||
| ) | |||
| endif() | |||
| @@ -1,60 +0,0 @@ | |||
| /** | |||
| * \file include/megcore_cambricon.h | |||
| * | |||
| * This file is part of MegDNN, a deep neural network run-time library | |||
| * developed by Megvii. | |||
| * | |||
| * \copyright Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| */ | |||
| #pragma once | |||
| #include "megcore.h" | |||
| #include <cndev.h> | |||
| #include <cnml.h> | |||
| #include <cnrt.h> | |||
| #include "megdnn/internal/visibility_prologue.h" | |||
| namespace megcore { | |||
| megcoreStatus_t createDeviceHandleWithGlobalInitStatus( | |||
| megcoreDeviceHandle_t* devHandle, int deviceID, unsigned int flags, | |||
| bool global_initialized); | |||
| struct CambriconContext { | |||
| cnrtQueue_t queue = nullptr; | |||
| CambriconContext() = default; | |||
| CambriconContext(cnrtQueue_t q) : queue{q} {} | |||
| }; | |||
| megcoreStatus_t createComputingHandleWithCambriconContext( | |||
| megcoreComputingHandle_t* compHandle, megcoreDeviceHandle_t devHandle, | |||
| unsigned int flags, const CambriconContext& ctx); | |||
| megcoreStatus_t getCambriconContext( | |||
| megcoreComputingHandle_t handle, CambriconContext* ctx); | |||
| } // namespace megcore | |||
| static inline megcoreStatus_t megcoreCreateComputingHandleWithCNRTQueue( | |||
| megcoreComputingHandle_t* compHandle, megcoreDeviceHandle_t devHandle, | |||
| unsigned int flags, cnrtQueue_t queue) { | |||
| megcore::CambriconContext ctx{queue}; | |||
| return megcore::createComputingHandleWithCambriconContext( | |||
| compHandle, devHandle, flags, ctx); | |||
| } | |||
| static inline megcoreStatus_t megcoreGetCNRTQueue( | |||
| megcoreComputingHandle_t handle, cnrtQueue_t* queue) { | |||
| megcore::CambriconContext ctx; | |||
| auto ret = megcore::getCambriconContext(handle, &ctx); | |||
| *queue = ctx.queue; | |||
| return ret; | |||
| } | |||
| #include "megdnn/internal/visibility_epilogue.h" | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,32 +0,0 @@ | |||
| load("//brain/megbrain/dnn:flags.bzl", "megdnn_opts") | |||
| load("@megvii3//tools/build_rules:bangc.bzl", "bangc_library") | |||
| package(default_visibility = ["//brain/megbrain/dnn:__subpackages__"]) | |||
| bangc_library( | |||
| name = "bangc_kernels", | |||
| srcs = glob([ | |||
| "**/*.mlu", | |||
| ]) + [ | |||
| "//brain/megbrain/dnn:src/common/utils.cuh", | |||
| ], | |||
| hdrs = glob([ | |||
| "**/*.mlu.h", | |||
| ]), | |||
| deps = [ | |||
| "//brain/megbrain/dnn:public_headers", | |||
| "//brain/megbrain/sdk/build_config", | |||
| ], | |||
| copts = megdnn_opts + [ | |||
| "-Ibrain/megbrain/dnn", | |||
| ], | |||
| ) | |||
| filegroup( | |||
| name = "cambricon_backend_files", | |||
| srcs = glob([ | |||
| "**/*.cpp", | |||
| "**/*.h", | |||
| "**/*.hpp", | |||
| ]), | |||
| ) | |||
| @@ -1,25 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/checksum/checksum.mlu.h | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include "src/cambricon/utils.mlu.h" | |||
| #ifdef __cplusplus | |||
| extern "C" { | |||
| #endif | |||
| void checksum_kernel_union1(uint32_t* dst, const uint32_t* src, int num_elems); | |||
| void checksum_kernel_union4(uint32_t* dst, const uint32_t* src, int num_elems); | |||
| #ifdef __cplusplus | |||
| } | |||
| #endif | |||
| // vim: ft=cpp syntax=cpp.doxygen | |||
| @@ -1,61 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/checksum/checksum_kernel_union1.mlu | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "checksum.mlu.h" | |||
| #include "cnsccl.h" | |||
| #include "mlu.h" | |||
| #define CLUSTER_DIM 1 | |||
| #define CORE_DIM 4 | |||
| #define STRIDE 1024 | |||
| __mlu_entry__ void checksum_kernel_union1(uint32_t* dst, uint32_t* src, | |||
| int nr_elems) { | |||
| __nram__ uint32_t sum = 0; | |||
| __nram__ uint32_t val[STRIDE]; | |||
| const uint32_t TASK_DIM = CLUSTER_DIM * CORE_DIM; | |||
| __mlu_shared__ uint32_t partial_sum[TASK_DIM]; | |||
| int task_stride = STRIDE; | |||
| int start_offset = taskId * task_stride; | |||
| int global_stride = taskDim * task_stride; | |||
| for (int task_offset = start_offset; task_offset < nr_elems; | |||
| task_offset += global_stride) { | |||
| int end_offset = task_offset + task_stride; | |||
| end_offset = end_offset > nr_elems ? nr_elems : end_offset; | |||
| int copy_elems = end_offset - task_offset; | |||
| __memcpy(val, src + task_offset, copy_elems * sizeof(uint32_t), | |||
| GDRAM2NRAM); | |||
| for (int i = 0; i < copy_elems; i++) { | |||
| sum = sum + val[i] * (task_offset + i + 1); | |||
| } | |||
| } | |||
| partial_sum[taskId] = sum; | |||
| __sync_cluster(); | |||
| if (taskId == 0) { | |||
| uint32_t res = 0; | |||
| for (int i = 0; i < taskDim; i++) { | |||
| res += partial_sum[i]; | |||
| } | |||
| dst[0] = res; | |||
| } | |||
| } | |||
| #undef CLUSTER_DIM | |||
| #undef CORE_DIM | |||
| #undef STRIDE | |||
| // vim: ft=cpp syntax=cpp.doxygen | |||
| @@ -1,71 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/checksum/checksum_kernel_union4.mlu | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "checksum.mlu.h" | |||
| #include "cnsccl.h" | |||
| #include "mlu.h" | |||
| #define CLUSTER_DIM 4 | |||
| #define CORE_DIM 4 | |||
| #define STRIDE 1024 | |||
| __mlu_entry__ void checksum_kernel_union4(uint32_t* dst, uint32_t* src, | |||
| int nr_elems) { | |||
| __nram__ uint32_t sum = 0; | |||
| __nram__ uint32_t val[STRIDE]; | |||
| __mlu_shared__ uint32_t partial_sum_send[CORE_DIM]; | |||
| __mlu_shared__ uint32_t partial_sum_recv[CLUSTER_DIM]; | |||
| int task_stride = STRIDE; | |||
| int start_offset = taskId * task_stride; | |||
| int global_stride = taskDim * task_stride; | |||
| for (int task_offset = start_offset; task_offset < nr_elems; | |||
| task_offset += global_stride) { | |||
| int end_offset = task_offset + task_stride; | |||
| end_offset = end_offset > nr_elems ? nr_elems : end_offset; | |||
| int copy_elems = end_offset - task_offset; | |||
| __memcpy(val, src + task_offset, copy_elems * sizeof(uint32_t), | |||
| GDRAM2NRAM); | |||
| for (int i = 0; i < copy_elems; i++) { | |||
| sum = sum + val[i] * (task_offset + i + 1); | |||
| } | |||
| } | |||
| partial_sum_send[coreId] = sum; | |||
| __sync_cluster(); | |||
| if (coreId == 0) { | |||
| for (int i = 1; i < CORE_DIM; ++i) { | |||
| partial_sum_send[0] += partial_sum_send[i]; | |||
| } | |||
| } | |||
| __sync_all(); | |||
| cnscclGather((void*)&partial_sum_send, (void*)&partial_sum_recv, 1, | |||
| cnscclInt, 0); | |||
| __sync_all(); | |||
| if (clusterId == 0 && coreId == 0) { | |||
| uint32_t res = 0; | |||
| for (int i = 0; i < CLUSTER_DIM; ++i) { | |||
| res += partial_sum_recv[i]; | |||
| } | |||
| dst[0] = res; | |||
| } | |||
| } | |||
| #undef CLUSTER_DIM | |||
| #undef CORE_DIM | |||
| #undef STRIDE | |||
| // vim: ft=cpp syntax=cpp.doxygen | |||
| @@ -1,85 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/checksum/opr_impl.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "src/cambricon/checksum/opr_impl.h" | |||
| #include "src/cambricon/checksum/checksum.mlu.h" | |||
| #include "src/cambricon/utils.h" | |||
| #include <algorithm> | |||
| using namespace megdnn; | |||
| using namespace cambricon; | |||
| namespace { | |||
| void bang_c_wrapper( | |||
| uint32_t* dst, const uint32_t* src, int nr_elems, cnrtQueue_t queue, | |||
| cnrtCoreVersion_t core_version) { | |||
| cnrtKernelParamsBuffer_t params; | |||
| cnrt_check(cnrtGetKernelParamsBuffer(¶ms)); | |||
| cnrt_check(cnrtKernelParamsBufferAddParam(params, &dst, sizeof(uint32_t*))); | |||
| cnrt_check(cnrtKernelParamsBufferAddParam(params, &src, sizeof(uint32_t*))); | |||
| cnrt_check(cnrtKernelParamsBufferAddParam(params, &nr_elems, sizeof(int))); | |||
| if (core_version == CNRT_MLU270) { | |||
| cnrtDim3_t dim; | |||
| dim.x = 16; | |||
| dim.y = 1; | |||
| dim.z = 1; | |||
| cnrtFunctionType_t c = CNRT_FUNC_TYPE_UNION4; | |||
| cnrt_check(cnrtInvokeKernel_V2( | |||
| (void*)&checksum_kernel_union4, dim, params, c, queue)); | |||
| } else if (core_version == CNRT_MLU220) { | |||
| cnrtDim3_t dim; | |||
| dim.x = 4; | |||
| dim.y = 1; | |||
| dim.z = 1; | |||
| cnrtFunctionType_t c = CNRT_FUNC_TYPE_UNION1; | |||
| cnrt_check(cnrtInvokeKernel_V2( | |||
| (void*)&checksum_kernel_union1, dim, params, c, queue)); | |||
| } | |||
| after_kernel_launch(); | |||
| cnrt_check(cnrtDestroyKernelParamsBuffer(params)); | |||
| } | |||
| } // namespace | |||
| size_t ChecksumForwardImpl::get_workspace_in_bytes(const TensorLayout& /* data */) { | |||
| size_t ws_size = sizeof(ChecksumForward::Result::checksum); | |||
| return ws_size; | |||
| } | |||
| ChecksumForward::Result ChecksumForwardImpl::exec( | |||
| _megdnn_tensor_in data, _megdnn_workspace workspace) { | |||
| Result result; | |||
| memset(&result, 0, sizeof(result)); | |||
| check_exec(data.layout, workspace.size); | |||
| auto queue = cnrt_queue(handle()); | |||
| auto ptr = static_cast<uint8_t*>(data.raw_ptr()); | |||
| size_t size_all = data.layout.shape[0], size_ints = size_all / sizeof(uint32_t); | |||
| auto last_val_size = std::min<size_t>(size_all, 4); | |||
| cnrt_check(cnrtMemcpyAsync( | |||
| &result.last_val, ptr + size_all - last_val_size, last_val_size, queue, | |||
| CNRT_MEM_TRANS_DIR_DEV2HOST)); | |||
| if (size_ints) { | |||
| auto&& device_info = current_device_info(); | |||
| bang_c_wrapper( | |||
| reinterpret_cast<uint32_t*>(workspace.raw_ptr), | |||
| static_cast<uint32_t*>(data.raw_ptr()), size_ints, queue, | |||
| device_info.core_version); | |||
| cnrt_check(cnrtMemcpyAsync( | |||
| &result.checksum, workspace.raw_ptr, sizeof(result.checksum), queue, | |||
| CNRT_MEM_TRANS_DIR_DEV2HOST)); | |||
| } | |||
| cnrt_check(cnrtSyncQueue(queue)); | |||
| return result; | |||
| } | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,34 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/checksum/opr_impl.h | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include "megdnn/oprs.h" | |||
| #include "src/cambricon/utils.h" | |||
| namespace megdnn { | |||
| namespace cambricon { | |||
| class ChecksumForwardImpl final : public ChecksumForward { | |||
| public: | |||
| using ChecksumForward::ChecksumForward; | |||
| size_t get_workspace_in_bytes(const TensorLayout&) override; | |||
| bool is_thread_safe() const override { return true; } | |||
| Result exec(_megdnn_tensor_in data, _megdnn_workspace workspace) override; | |||
| }; | |||
| } // namespace cambricon | |||
| } // namespace megdnn | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,67 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/handle.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "src/common/handle_impl.h" | |||
| #include "src/common/version_symbol.h" | |||
| #include "src/cambricon/handle.h" | |||
| #include "src/cambricon/utils.h" | |||
| #include <cnrt.h> | |||
| #include "src/cambricon/checksum/opr_impl.h" | |||
| namespace megdnn { | |||
| namespace cambricon { | |||
| HandleImpl::HandleImpl(megcoreComputingHandle_t comp_handle) | |||
| : HandleImplHelper(comp_handle, HandleType::CAMBRICON) { | |||
| // Get megcore device handle | |||
| megcoreDeviceHandle_t dev_handle; | |||
| megcoreGetDeviceHandle(comp_handle, &dev_handle); | |||
| int dev_id; | |||
| megcoreGetDeviceID(dev_handle, &dev_id); | |||
| unsigned int dev_num; | |||
| cnrt_check(cnrtGetDeviceCount(&dev_num)); | |||
| MEGDNN_MARK_USED_VAR(dev_num); | |||
| // check validity of device_id | |||
| megdnn_assert(dev_id >= 0 && static_cast<unsigned int>(dev_id) < dev_num); | |||
| m_device_id = dev_id; | |||
| cnrt_check(cnrtGetDeviceInfo(&m_device_info, dev_id)); | |||
| megcore::getCambriconContext(comp_handle, &m_megcore_context); | |||
| } | |||
| HandleImpl::~HandleImpl() noexcept = default; | |||
| template <typename Opr> | |||
| std::unique_ptr<Opr> HandleImpl::create_operator() { | |||
| megdnn_throw("unsupported cambricon opr"); | |||
| return nullptr; | |||
| } | |||
| size_t HandleImpl::alignment_requirement() const { | |||
| return 1; | |||
| } | |||
| MEGDNN_SPECIALIZE_CREATE_OPERATOR(ChecksumForward); | |||
| #pragma GCC diagnostic push | |||
| #pragma GCC diagnostic ignored "-Wpragmas" | |||
| #pragma GCC diagnostic ignored "-Winstantiation-after-specialization" | |||
| MEGDNN_FOREACH_OPR_CLASS(MEGDNN_INST_CREATE_OPERATOR) | |||
| #pragma GCC diagnostic pop | |||
| } // namespace cambricon | |||
| } // namespace megdnn | |||
| MEGDNN_VERSION_SYMBOL3( | |||
| CNRT, CNRT_MAJOR_VERSION, CNRT_MINOR_VERSION, CNRT_PATCH_VERSION); | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,64 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/handle.h | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include "megcore_cambricon.h" | |||
| #include "megdnn/basic_types.h" | |||
| #include "megdnn/handle.h" | |||
| #include "megdnn/oprs/general.h" | |||
| #include "src/common/handle_impl.h" | |||
| #include "src/common/utils.h" | |||
| #include <atomic> | |||
| #include <mutex> | |||
| #include <cnrt.h> | |||
| namespace megdnn { | |||
| namespace cambricon { | |||
| class HandleImpl : public HandleImplHelper { | |||
| public: | |||
| HandleImpl(megcoreComputingHandle_t computing_handle); | |||
| ~HandleImpl() noexcept; | |||
| size_t alignment_requirement() const override; | |||
| const cnrtDeviceInfo_t& device_info() const { return m_device_info; } | |||
| template <typename Opr> | |||
| std::unique_ptr<Opr> create_operator(); | |||
| const megcore::CambriconContext& megcore_context() const { | |||
| return m_megcore_context; | |||
| } | |||
| int device_id() const { return m_device_id; } | |||
| cnrtQueue_t queue() const { return megcore_context().queue; } | |||
| //! global matmul opr | |||
| Checksum* checksum_opr() override final { | |||
| return get_helper_opr<Checksum, 0>(this); | |||
| } | |||
| private: | |||
| int m_device_id; | |||
| //! MegDNN handle does not manage the lifetime of cnrt queue. | |||
| megcore::CambriconContext m_megcore_context; | |||
| cnrtDeviceInfo_t m_device_info; | |||
| }; | |||
| } // namespace cambricon | |||
| } // namespace megdnn | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,75 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/megcore/cambricon_computing_context.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "megcore.h" | |||
| #include "src/cambricon/utils.h" | |||
| #include "src/common/utils.h" | |||
| #include "src/cambricon/megcore/cambricon_computing_context.hpp" | |||
| using namespace megcore; | |||
| using namespace megcore::cambricon; | |||
| CambriconComputingContext::CambriconComputingContext( | |||
| megcoreDeviceHandle_t dev_handle, unsigned int flags, | |||
| const CambriconContext& ctx) | |||
| : ComputingContext(dev_handle, flags), | |||
| own_queue{ctx.queue == nullptr}, | |||
| context_{ctx} { | |||
| megcorePlatform_t platform; | |||
| megcoreGetPlatform(dev_handle, &platform); | |||
| megdnn_assert(platform == megcorePlatformCambricon); | |||
| if (own_queue) { | |||
| cnrt_check(cnrtCreateQueue(&context_.queue)); | |||
| } | |||
| } | |||
| CambriconComputingContext::~CambriconComputingContext() { | |||
| if (own_queue) { | |||
| cnrt_check(cnrtDestroyQueue(context_.queue)); | |||
| } | |||
| } | |||
| void CambriconComputingContext::memcpy( | |||
| void* dst, const void* src, size_t size_in_bytes, megcoreMemcpyKind_t kind) { | |||
| cnrtMemTransDir_t dir; | |||
| switch (kind) { | |||
| case megcoreMemcpyDeviceToHost: | |||
| dir = CNRT_MEM_TRANS_DIR_DEV2HOST; | |||
| break; | |||
| case megcoreMemcpyHostToDevice: | |||
| dir = CNRT_MEM_TRANS_DIR_HOST2DEV; | |||
| break; | |||
| case megcoreMemcpyDeviceToDevice: | |||
| dir = CNRT_MEM_TRANS_DIR_DEV2DEV; | |||
| break; | |||
| default: | |||
| megdnn_throw("bad cnrt mem trans dir"); | |||
| } | |||
| if (kind == megcoreMemcpyDeviceToDevice) { | |||
| cnrt_check(cnrtSyncQueue(context_.queue)); | |||
| cnrt_check(cnrtMemcpy(dst, const_cast<void*>(src), size_in_bytes, dir)); | |||
| return; | |||
| } | |||
| cnrt_check(cnrtMemcpyAsync( | |||
| dst, const_cast<void*>(src), size_in_bytes, context_.queue, dir)); | |||
| } | |||
| void CambriconComputingContext::memset(void* dst, int value, size_t size_in_bytes) { | |||
| cnrt_check(cnrtSyncQueue(context_.queue)); | |||
| cnrt_check(cnrtMemset(dst, value, size_in_bytes)); | |||
| } | |||
| void CambriconComputingContext::synchronize() { | |||
| cnrt_check(cnrtSyncQueue(context_.queue)); | |||
| } | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,44 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/megcore/cambricon_computing_context.hpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include "megcore_cambricon.h" | |||
| #include "src/common/megcore/common/computing_context.hpp" | |||
| namespace megcore { | |||
| namespace cambricon { | |||
| class CambriconComputingContext final : public ComputingContext { | |||
| public: | |||
| CambriconComputingContext(megcoreDeviceHandle_t dev_handle, | |||
| unsigned int flags, | |||
| const CambriconContext& ctx = {}); | |||
| ~CambriconComputingContext(); | |||
| void memcpy(void* dst, const void* src, size_t size_in_bytes, | |||
| megcoreMemcpyKind_t kind) override; | |||
| void memset(void* dst, int value, size_t size_in_bytes) override; | |||
| void synchronize() override; | |||
| const CambriconContext& context() const { return context_; } | |||
| cnrtQueue_t queue() const { return context().queue; } | |||
| private: | |||
| bool own_queue; | |||
| CambriconContext context_; | |||
| }; | |||
| } // namespace cambricon | |||
| } // namespace megcore | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,77 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/megcore/cambricon_device_context.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "megcore.h" | |||
| #include "src/cambricon/utils.h" | |||
| #include "src/common/utils.h" | |||
| #include "src/cambricon/megcore/cambricon_device_context.hpp" | |||
| #define STR_HELPER(x) #x | |||
| #define STR(x) STR_HELPER(x) | |||
| #define CNRT_VERSION_STR \ | |||
| STR(CNRT_MAJOR_VERSION) \ | |||
| "." STR(CNRT_MINOR_VERSION) "." STR(CNRT_PATCH_VERSION) | |||
| #pragma message "compile with cnrt " CNRT_VERSION_STR " " | |||
| #undef STR_HELPER | |||
| #undef STR | |||
| using namespace megcore; | |||
| using namespace cambricon; | |||
| CambriconDeviceContext::CambriconDeviceContext( | |||
| int device_id, unsigned int flags, bool global_initialized) | |||
| : DeviceContext(megcorePlatformCambricon, device_id, flags) { | |||
| if (!global_initialized) | |||
| init_status.init(); | |||
| unsigned int version; | |||
| cnrt_check(cnrtGetVersion(&version)); | |||
| megdnn_assert( | |||
| version == CNRT_VERSION, "megcore compiled with cnrt %d, get %d at runtime", | |||
| CNRT_VERSION, version); | |||
| unsigned int dev_num; | |||
| cnrt_check(cnrtGetDeviceCount(&dev_num)); | |||
| MEGDNN_MARK_USED_VAR(dev_num); | |||
| // check validity of device_id | |||
| megdnn_assert(device_id >= 0 && static_cast<unsigned int>(device_id) < dev_num); | |||
| cnrt_check(cnrtGetDeviceInfo(&device_info, device_id)); | |||
| } | |||
| CambriconDeviceContext::~CambriconDeviceContext() noexcept = default; | |||
| size_t CambriconDeviceContext::mem_alignment_in_bytes() const noexcept { | |||
| return 1; | |||
| } | |||
| void CambriconDeviceContext::activate() { | |||
| int id = device_id(); | |||
| cnrtDev_t dev; | |||
| cnrt_check(cnrtGetDeviceHandle(&dev, id)); | |||
| cnrt_check(cnrtSetCurrentDevice(dev)); | |||
| } | |||
| void* CambriconDeviceContext::malloc(size_t size_in_bytes) { | |||
| void* ptr; | |||
| cnrt_check(cnrtMalloc(&ptr, size_in_bytes)); | |||
| return ptr; | |||
| } | |||
| void CambriconDeviceContext::free(void* ptr) { | |||
| cnrt_check(cnrtFree(ptr)); | |||
| } | |||
| CambriconDeviceContext::InitStatus CambriconDeviceContext::init_status; | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,63 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/megcore/cambricon_device_context.hpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include <mutex> | |||
| #include "megcore_cambricon.h" | |||
| #include "src/common/megcore/common/device_context.hpp" | |||
| #include "src/common/utils.h" | |||
| namespace megcore { | |||
| namespace cambricon { | |||
| class CambriconDeviceContext : public DeviceContext { | |||
| public: | |||
| CambriconDeviceContext(int device_id, unsigned int flags, | |||
| bool global_initialized = false); | |||
| ~CambriconDeviceContext() noexcept; | |||
| size_t mem_alignment_in_bytes() const noexcept override; | |||
| void activate() override; | |||
| void* malloc(size_t size_in_bytes) override; | |||
| void free(void* ptr) override; | |||
| struct InitStatus { | |||
| bool initialized; | |||
| std::mutex mtx; | |||
| InitStatus() : initialized{false} {} | |||
| void init() { | |||
| std::lock_guard<std::mutex> guard{mtx}; | |||
| if (!initialized) { | |||
| auto cnrt_err = cnrtInit(0); | |||
| initialized = cnrt_err == CNRT_RET_SUCCESS; | |||
| megdnn_assert(initialized, "cnrt initialize failed: (cnrt:%d)", | |||
| static_cast<int>(cnrt_err)); | |||
| } | |||
| } | |||
| ~InitStatus() { | |||
| if (initialized) { | |||
| cnrtDestroy(); | |||
| initialized = false; | |||
| } | |||
| } | |||
| }; | |||
| static InitStatus init_status; | |||
| private: | |||
| cnrtDeviceInfo_t device_info; | |||
| }; | |||
| } // namespace cambricon | |||
| } // namespace megcore | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,57 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/megcore/public_api/computing.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "megcore_cambricon.h" | |||
| #include "src/cambricon/megcore/cambricon_computing_context.hpp" | |||
| #include "src/cambricon/megcore/cambricon_device_context.hpp" | |||
| #include "src/common/megcore/public_api/computing.hpp" | |||
| #include "src/common/megcore/public_api/device.hpp" | |||
| #include "src/common/utils.h" | |||
| using namespace megcore; | |||
| megcoreStatus_t megcore::createDeviceHandleWithGlobalInitStatus( | |||
| megcoreDeviceHandle_t* devHandle, int deviceID, unsigned int flags, | |||
| bool global_initialized) { | |||
| auto content = megdnn::make_unique<cambricon::CambriconDeviceContext>( | |||
| deviceID, flags, global_initialized); | |||
| auto& ctx = *devHandle; | |||
| ctx = new megcoreDeviceContext; | |||
| ctx->content = std::move(content); | |||
| return megcoreSuccess; | |||
| } | |||
| megcoreStatus_t megcore::createComputingHandleWithCambriconContext( | |||
| megcoreComputingHandle_t* compHandle, megcoreDeviceHandle_t devHandle, | |||
| unsigned int flags, const CambriconContext& ctx) { | |||
| auto content = megdnn::make_unique<cambricon::CambriconComputingContext>( | |||
| devHandle, flags, ctx); | |||
| auto& H = *compHandle; | |||
| H = new megcoreComputingContext; | |||
| H->content = std::move(content); | |||
| return megcoreSuccess; | |||
| } | |||
| megcoreStatus_t megcore::getCambriconContext( | |||
| megcoreComputingHandle_t handle, CambriconContext* ctx) { | |||
| auto&& H = handle; | |||
| megdnn_assert(H); | |||
| megcoreDeviceHandle_t dev_handle = H->content->dev_handle(); | |||
| megcorePlatform_t platform; | |||
| megcoreGetPlatform(dev_handle, &platform); | |||
| megdnn_assert(platform == megcorePlatformCambricon); | |||
| auto context = static_cast<megcore::cambricon::CambriconComputingContext*>( | |||
| H->content.get()); | |||
| *ctx = context->context(); | |||
| return megcoreSuccess; | |||
| } | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,75 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/utils.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "src/cambricon/utils.h" | |||
| #include "src/cambricon/utils.mlu.h" | |||
| #include "src/cambricon/handle.h" | |||
| #include "src/common/utils.h" | |||
| #include <mutex> | |||
| #include <unordered_map> | |||
| using namespace megdnn; | |||
| using namespace cambricon; | |||
| namespace { | |||
| struct DeviceInfoRecord { | |||
| bool init = false; | |||
| cnrtDeviceInfo_t device_info; | |||
| std::mutex mtx; | |||
| }; | |||
| std::unordered_map<cnrtDev_t, int> dev2device_id; | |||
| std::mutex dev2device_id_mtx; | |||
| constexpr int MAX_NR_DEVICE = 64; | |||
| DeviceInfoRecord device_info_rec[MAX_NR_DEVICE]; | |||
| } // namespace | |||
| void cambricon::__throw_cnrt_error__(cnrtRet_t err, const char* msg) { | |||
| auto s = ssprintf( | |||
| "cnrt return %s(%d) occurred; expr: %s", cnrtGetErrorStr(err), int(err), | |||
| msg); | |||
| megdnn_throw(s.c_str()); | |||
| } | |||
| cnrtDeviceInfo_t cambricon::current_device_info() { | |||
| static bool dev2device_id_init = false; | |||
| { | |||
| std::lock_guard<std::mutex> lock(dev2device_id_mtx); | |||
| if (!dev2device_id_init) { | |||
| unsigned int dev_num = 0; | |||
| cnrt_check(cnrtGetDeviceCount(&dev_num)); | |||
| for (unsigned int dev_id = 0; dev_id < dev_num; ++dev_id) { | |||
| cnrtDev_t dev; | |||
| cnrt_check(cnrtGetDeviceHandle(&dev, dev_id)); | |||
| dev2device_id[dev] = dev_id; | |||
| } | |||
| dev2device_id_init = true; | |||
| } | |||
| } | |||
| cnrtDev_t dev; | |||
| cnrt_check(cnrtGetCurrentDevice(&dev)); | |||
| { | |||
| std::lock_guard<std::mutex> lock(dev2device_id_mtx); | |||
| int dev_id = dev2device_id.at(dev); | |||
| auto& rec = device_info_rec[dev_id]; | |||
| { | |||
| std::lock_guard<std::mutex> lock(rec.mtx); | |||
| if (!rec.init) { | |||
| cnrt_check(cnrtGetDeviceInfo(&rec.device_info, dev_id)); | |||
| rec.init = true; | |||
| } | |||
| } | |||
| return rec.device_info; | |||
| } | |||
| } | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,39 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/utils.h | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include "megcore_cdefs.h" | |||
| #include "megdnn/handle.h" | |||
| #include "src/cambricon/utils.mlu.h" | |||
| #include "src/common/utils.h" | |||
| #include "src/cambricon/handle.h" | |||
| #include <cnrt.h> | |||
| namespace megdnn { | |||
| namespace cambricon { | |||
| static inline HandleImpl* concrete_handle(Handle* handle) { | |||
| return static_cast<cambricon::HandleImpl*>(handle); | |||
| } | |||
| static inline cnrtQueue_t cnrt_queue(Handle* handle) { | |||
| return concrete_handle(handle)->queue(); | |||
| } | |||
| //! get device info of current active device | |||
| cnrtDeviceInfo_t current_device_info(); | |||
| } // namespace cambricon | |||
| } // namespace megdnn | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,41 +0,0 @@ | |||
| /** | |||
| * \file dnn/src/cambricon/utils.mlu.h | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include "src/common/utils.cuh" | |||
| #include <stdint.h> | |||
| #include <cnrt.h> | |||
| #define cnrt_check(_x) \ | |||
| do { \ | |||
| cnrtRet_t _ret = (_x); \ | |||
| if (_ret != CNRT_RET_SUCCESS) { \ | |||
| ::megdnn::cambricon::__throw_cnrt_error__(_ret, #_x); \ | |||
| } \ | |||
| } while (0) | |||
| #define after_kernel_launch() \ | |||
| do { \ | |||
| cnrt_check(cnrtGetLastErr()); \ | |||
| } while (0) | |||
| namespace megdnn { | |||
| namespace cambricon { | |||
| //! Error handling funcions | |||
| MEGDNN_NORETURN void __throw_cnrt_error__(cnrtRet_t err, const char* msg); | |||
| } // namespace cambricon | |||
| } // namespace megdnn | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,70 +0,0 @@ | |||
| /** | |||
| * \file dnn/test/cambricon/checksum.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "megdnn/oprs.h" | |||
| #include "test/cambricon/fixture.h" | |||
| #include "test/common/checker.h" | |||
| using namespace megdnn; | |||
| using namespace test; | |||
| TEST_F(CAMBRICON, CHECKSUM_FORWARD) { | |||
| auto cambricon_opr = handle_cambricon()->create_operator<megdnn::Checksum>(), | |||
| naive_opr = handle_naive()->create_operator<megdnn::Checksum>(); | |||
| std::mt19937 rng(std::random_device{}()); | |||
| for (size_t size : {3, 8, 4 * 4 * 1024, 12345, 1024 * 1024, 1024 * 1024 * 10}) { | |||
| auto aligned_size = size + ((512 - size % 512) % 512); | |||
| auto run = [&](megdnn::Checksum* opr, void* ptr, bool log_size) { | |||
| TensorND tensor; | |||
| tensor.reset_ptr(ptr); | |||
| tensor.layout.init_contiguous_stride({size}); | |||
| tensor.layout.dtype = dtype::Byte(); | |||
| WorkspaceWrapper workspace( | |||
| handle_cambricon(), opr->get_workspace_in_bytes(tensor.layout)); | |||
| if (log_size) { | |||
| printf("checksum(%zu): workspace=%zu\n", size, | |||
| workspace.workspace().size); | |||
| } | |||
| return opr->exec(tensor, workspace.workspace()); | |||
| }; | |||
| std::vector<uint8_t> buf(aligned_size); | |||
| for (size_t i = 0; i < size; ++i) | |||
| buf[i] = 1; | |||
| auto run_offsset = [&](size_t offset) { | |||
| void* dev_ptr = megdnn_malloc(handle_cambricon(), buf.size() + offset); | |||
| void* dev_buf = static_cast<char*>(dev_ptr) + offset; | |||
| Checksum::Result res_cambricon[2], res_naive[2]; | |||
| for (int change_last = 0; change_last < 2; ++change_last) { | |||
| if (change_last) | |||
| ++buf[size - 1]; | |||
| megdnn_memcpy_H2D(handle_cambricon(), dev_buf, buf.data(), size); | |||
| res_cambricon[change_last] = | |||
| run(cambricon_opr.get(), dev_buf, !change_last); | |||
| res_naive[change_last] = run(naive_opr.get(), buf.data(), false); | |||
| } | |||
| megdnn_free(handle_cambricon(), dev_ptr); | |||
| ASSERT_EQ(res_naive[0], res_cambricon[0]) << "failed for size " << size; | |||
| ASSERT_EQ(res_naive[1], res_cambricon[1]); | |||
| ASSERT_NE(res_cambricon[0], res_cambricon[1]); | |||
| }; | |||
| for (size_t i = 0; i < 8; ++i) { | |||
| run_offsset(i); | |||
| } | |||
| } | |||
| } | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,49 +0,0 @@ | |||
| /** | |||
| * \file dnn/test/cambricon/fixture.cpp | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #include "test/cambricon/fixture.h" | |||
| #include "src/cambricon/handle.h" | |||
| #include "src/cambricon/utils.h" | |||
| #include "test/common/memory_manager.h" | |||
| #include "test/common/random_state.h" | |||
| #include "test/common/utils.h" | |||
| #include <cnrt.h> | |||
| #include <cstdlib> | |||
| using namespace megdnn; | |||
| using namespace test; | |||
| void CAMBRICON::SetUp() { | |||
| RandomState::reset(); | |||
| megcoreDeviceHandle_t dev_handle; | |||
| // use card 0 | |||
| megcore_check(megcoreCreateDeviceHandle(&dev_handle, megcorePlatformCambricon, 0)); | |||
| megcoreComputingHandle_t comp_handle; | |||
| megcore_check(megcoreCreateComputingHandle(&comp_handle, dev_handle)); | |||
| m_handle_cambricon = Handle::make(comp_handle); | |||
| megdnn_assert(m_handle_cambricon); | |||
| } | |||
| Handle* CAMBRICON::handle_naive() { | |||
| if (!m_handle_naive) | |||
| m_handle_naive = create_cpu_handle(2); | |||
| return m_handle_naive.get(); | |||
| } | |||
| void CAMBRICON::TearDown() { | |||
| m_handle_naive.reset(); | |||
| m_handle_cambricon.reset(); | |||
| MemoryManagerHolder::instance()->clear(); | |||
| } | |||
| // vim: syntax=cpp.doxygen | |||
| @@ -1,39 +0,0 @@ | |||
| /** | |||
| * \file dnn/test/cambricon/fixture.h | |||
| * MegEngine is Licensed under the Apache License, Version 2.0 (the "License") | |||
| * | |||
| * Copyright (c) 2014-2021 Megvii Inc. All rights reserved. | |||
| * | |||
| * Unless required by applicable law or agreed to in writing, | |||
| * software distributed under the License is distributed on an | |||
| * "AS IS" BASIS, WITHOUT ARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||
| */ | |||
| #pragma once | |||
| #include <gtest/gtest.h> | |||
| #include "test/common/fix_gtest_on_platforms_without_exception.inl" | |||
| #include "megcore_cdefs.h" | |||
| #include "megdnn/handle.h" | |||
| #include <memory> | |||
| namespace megdnn { | |||
| namespace test { | |||
| class CAMBRICON : public ::testing::Test { | |||
| public: | |||
| void SetUp() override; | |||
| void TearDown() override; | |||
| Handle* handle_cambricon() { return m_handle_cambricon.get(); } | |||
| Handle* handle_naive(); | |||
| private: | |||
| std::unique_ptr<Handle> m_handle_naive; | |||
| std::unique_ptr<Handle> m_handle_cambricon; | |||
| }; | |||
| } // namespace test | |||
| } // namespace megdnn | |||
| // vim: syntax=cpp.doxygen | |||