Browse Source

fix(mge/functional): fix default dtype of F.full

GitOrigin-RevId: 5cd34af9bf
release-1.7
Megvii Engine Team 3 years ago
parent
commit
846cc13ca8
6 changed files with 1423 additions and 7 deletions
  1. +1012
    -0
      cmake/FindBANG/FindBANG.cmake
  2. +84
    -0
      cmake/FindBANG/make2cmake.cmake
  3. +103
    -0
      cmake/FindBANG/parse_cnbin.cmake
  4. +200
    -0
      cmake/FindBANG/run_cncc.cmake
  5. +16
    -7
      imperative/python/megengine/functional/tensor.py
  6. +8
    -0
      imperative/python/test/unit/functional/test_tensor.py

+ 1012
- 0
cmake/FindBANG/FindBANG.cmake
File diff suppressed because it is too large
View File


+ 84
- 0
cmake/FindBANG/make2cmake.cmake View File

@@ -0,0 +1,84 @@
# 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")

+ 103
- 0
cmake/FindBANG/parse_cnbin.cmake View File

@@ -0,0 +1,103 @@
# 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()



+ 200
- 0
cmake/FindBANG/run_cncc.cmake View File

@@ -0,0 +1,200 @@
# 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()

+ 16
- 7
imperative/python/megengine/functional/tensor.py View File

@@ -98,18 +98,27 @@ def eye(N, M=None, *, dtype="float32", device: Optional[CompNode] = None) -> Ten
return result


def full(shape, value, dtype="float32", device=None) -> Tensor:
def full(
shape: Union[int, tuple, list],
value: Union[bool, int, float, Tensor],
dtype=None,
device=None,
) -> Tensor:
r"""Creates a tensor of shape ``shape`` filled with ``value``.

Args:
shape: a list, tuple or integer defining the shape of the output tensor.
value: the value to fill the output tensor with.
dtype: the desired data type of the output tensor. Default: ``float32``.
device: the desired device of the output tensor. Default: if ``None``,
use the default device (see :func:`~.megengine.get_default_device`).
shape: output tensor shape.
value: fill value.
dtype: output tensor data type. If ``dtype`` is ``None``, the output tensor
data type must be inferred from ``value``. If the value is an ``int``,
the output tensor data type must be the default integer data type. If the
value is a ``float``, the output tensor data type must be the default
floating-point data type. If the value is a ``bool``, the output tensor
must have boolean data type. Default: ``None``.
device: device on which to place the created tensor. Default: ``None``.

Returns:
output tensor.
a tensor where every element is equal to ``value``.

Examples:



+ 8
- 0
imperative/python/test/unit/functional/test_tensor.py View File

@@ -41,6 +41,14 @@ def test_eye():
)


def test_full():
shape = (2, 3)
values = [True, 4, 5.0]
for value in values:
np.testing.assert_allclose(F.full(shape, value).numpy(), np.full(shape, value))
assert F.full(shape, value).dtype == tensor(value).dtype


@pytest.mark.parametrize("is_varnode", [True, False])
def test_concat(is_varnode):
if is_varnode:


Loading…
Cancel
Save