Unverified Commit 97d4bb6c authored by Ted Themistokleous's avatar Ted Themistokleous Committed by GitHub
Browse files

Merge branch 'develop' into add_parity_check_ci

parents 39b097c7 bdbc38bc
...@@ -4,62 +4,7 @@ ...@@ -4,62 +4,7 @@
# are installed, and if so, uses the installed version to format # are installed, and if so, uses the installed version to format
# the staged changes. # the staged changes.
base=clang-format-10
format=""
yapf_base=yapf
yapf_format=""
use_yapf=true
# Redirect output to stderr.
exec 1>&2
# check if clang-format is installed
type "$base" >/dev/null 2>&1 && format="$base"
# no versions of clang-format are installed
if [ -z "$format" ]
then
echo "$base is not installed. Pre-commit hook will not be executed."
exit 0
fi
# check if yapf is installed
type "$yapf_base" >/dev/null 2>&1 && yapf_format="$yapf_base"
# no versions of yapf are installed
if [ -z "$yapf_format" ]
then
echo "$yapf_base is not installed. Pre-commit hook for python files will not be executed"
use_yapf=false
fi
# Do everything from top - level # Do everything from top - level
cd $(git rev-parse --show-toplevel) cd $(git rev-parse --show-toplevel)
if git rev-parse --verify HEAD >/dev/null 2>&1 python3 tools/format.py -q -i HEAD
then
against=HEAD
else
# Initial commit: diff against an empty tree object
against=16bbb57
fi
# do the formatting
for file in $(git diff-index --cached --name-only $against | grep -E '\.h$|\.hpp$|\.cpp$|\.cl$|\.c$|\.h\.in$|\.hpp\.in$|\.cpp\.in$|\.py$')
do
if [ -e "$file" ]
then
if [ $(echo $file | grep -E '\.py$') ]
then
if $use_yapf
then
echo "$yapf_format $file"
"$yapf_format" -i "$file"
fi
else
echo "$format $file"
"$format" -i -style=file "$file"
fi
fi
done
...@@ -144,6 +144,8 @@ jobs: ...@@ -144,6 +144,8 @@ jobs:
runs-on: ROCM-Ubuntu runs-on: ROCM-Ubuntu
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
with:
fetch-depth: 0
# In this step, this action saves a list of existing images, # In this step, this action saves a list of existing images,
# the cache is created without them in the post run. # the cache is created without them in the post run.
...@@ -164,19 +166,8 @@ jobs: ...@@ -164,19 +166,8 @@ jobs:
shell: bash -c "docker run -i -v=$GITHUB_WORKSPACE:/data -w /data migraphx bash < {0}" shell: bash -c "docker run -i -v=$GITHUB_WORKSPACE:/data -w /data migraphx bash < {0}"
run: | run: |
set -e set -e
find . -iname '*.h' \ git config --global --add safe.directory /data
-o -iname '*.hpp' \ python3 tools/format.py origin/${{ github.event_name == 'pull_request' && github.base_ref || 'develop' }}
-o -iname '*.cpp' \
-o -iname '*.h.in' \
-o -iname '*.hpp.in' \
-o -iname '*.cpp.in' \
-o -iname '*.cl' \
-o -iname '*.c' \
| grep -v 'build/' \
| xargs -n 1 -P 1 -I{} -t sh -c 'clang-format-10 -style=file {} | diff - {}'
find . -iname '*.py' \
| grep -v 'build/' \
| xargs -n 1 -P 1 -I{} -t sh -c 'yapf {} | diff - {}'
pyflakes: pyflakes:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
...@@ -323,6 +314,7 @@ jobs: ...@@ -323,6 +314,7 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
set +x
gh extension install actions/gh-actions-cache --pin v1.0.1 gh extension install actions/gh-actions-cache --pin v1.0.1
gh actions-cache delete ${{ steps.ccache_restore.outputs.cache-matched-key }} --confirm gh actions-cache delete ${{ steps.ccache_restore.outputs.cache-matched-key }} --confirm
...@@ -439,6 +431,7 @@ jobs: ...@@ -439,6 +431,7 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
set +x
gh extension install actions/gh-actions-cache gh extension install actions/gh-actions-cache
gh actions-cache delete ${{ steps.ccache_restore_fpga.outputs.cache-matched-key }} --confirm gh actions-cache delete ${{ steps.ccache_restore_fpga.outputs.cache-matched-key }} --confirm
continue-on-error: true continue-on-error: true
......
...@@ -12,7 +12,7 @@ on: ...@@ -12,7 +12,7 @@ on:
rocm_release: rocm_release:
description: ROCm Version description: ROCm Version
required: true required: true
default: '5.5' default: '5.6'
performance_reports_repo: performance_reports_repo:
description: Repository where performance reports are stored description: Repository where performance reports are stored
required: true required: true
...@@ -42,13 +42,15 @@ on: ...@@ -42,13 +42,15 @@ on:
required: true required: true
default: '-r' default: '-r'
concurrency: "perftest-${{ github.head_ref || github.base_ref || 'schedule' }}" concurrency:
group: "perftest-${{ github.head_ref || github.base_ref || 'schedule' }}"
cancel-in-progress: true
jobs: jobs:
release: release:
uses: ROCmSoftwarePlatform/migraphx-benchmark/.github/workflows/perf-test.yml@main uses: ROCmSoftwarePlatform/migraphx-benchmark/.github/workflows/perf-test.yml@main
with: with:
rocm_release: ${{ github.event.inputs.rocm_release || '5.5' }} rocm_release: ${{ github.event.inputs.rocm_release || '5.6' }}
result_number: ${{ github.event.inputs.result_number || '10' }} result_number: ${{ github.event.inputs.result_number || '10' }}
flags: ${{ github.event.inputs.flags || '-r' }} flags: ${{ github.event.inputs.flags || '-r' }}
performance_reports_repo: ${{ github.event.inputs.performance_reports_repo || 'ROCmSoftwarePlatform/migraphx-reports' }} performance_reports_repo: ${{ github.event.inputs.performance_reports_repo || 'ROCmSoftwarePlatform/migraphx-reports' }}
......
...@@ -70,5 +70,13 @@ docs/_images ...@@ -70,5 +70,13 @@ docs/_images
docs/_static docs/_static
docs/_templates docs/_templates
docs/.doxygen/docBin docs/.doxygen/docBin
docs/.doxygen/DoxygenWarningLog.txt
docs/_doxygen docs/_doxygen
docs/html
/_readthedocs /_readthedocs
# JetBrains config directories (ignoring symlinks)
.idea/
cmake-build*/
build*/
...@@ -43,6 +43,8 @@ else() ...@@ -43,6 +43,8 @@ else()
endif() endif()
endif() endif()
set(CMAKE_INSTALL_PREFIX "/opt/rocm" CACHE PATH "")
set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/lib") set(CMAKE_BUILD_RPATH "${CMAKE_BINARY_DIR}/lib")
project(migraphx LANGUAGES C CXX) project(migraphx LANGUAGES C CXX)
...@@ -114,6 +116,7 @@ rocm_enable_clang_tidy( ...@@ -114,6 +116,7 @@ rocm_enable_clang_tidy(
llvm-namespace-comment llvm-namespace-comment
misc-* misc-*
-misc-confusable-identifiers -misc-confusable-identifiers
-misc-use-anonymous-namespace
modernize-* modernize-*
performance-* performance-*
readability-* readability-*
......
...@@ -7,10 +7,10 @@ RUN dpkg --add-architecture i386 ...@@ -7,10 +7,10 @@ RUN dpkg --add-architecture i386
# Install rocm key # Install rocm key
RUN apt-get update && apt-get install -y gnupg2 --no-install-recommends curl && \ RUN apt-get update && apt-get install -y gnupg2 --no-install-recommends curl && \
curl -sL http://repo.radeon.com/rocm/rocm.gpg.key | apt-key add - curl -sL http://repo.radeon.com/rocm/rocm.gpg.key | apt-key add -
# Add rocm repository # Add rocm repository
RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.5/ focal main > /etc/apt/sources.list.d/rocm.list' RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.6/ focal main > /etc/apt/sources.list.d/rocm.list'
# From docs.amd.com for installing rocm. Needed to install properly # From docs.amd.com for installing rocm. Needed to install properly
RUN sh -c "echo 'Package: *\nPin: release o=repo.radeon.com\nPin-priority: 600' > /etc/apt/preferences.d/rocm-pin-600" RUN sh -c "echo 'Package: *\nPin: release o=repo.radeon.com\nPin-priority: 600' > /etc/apt/preferences.d/rocm-pin-600"
...@@ -19,7 +19,6 @@ RUN sh -c "echo 'Package: *\nPin: release o=repo.radeon.com\nPin-priority: 600' ...@@ -19,7 +19,6 @@ RUN sh -c "echo 'Package: *\nPin: release o=repo.radeon.com\nPin-priority: 600'
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \
apt-utils \ apt-utils \
build-essential \ build-essential \
clang-format-10 \
cmake \ cmake \
curl \ curl \
doxygen \ doxygen \
...@@ -97,7 +96,8 @@ RUN /download_models.sh && rm /download_models.sh ...@@ -97,7 +96,8 @@ RUN /download_models.sh && rm /download_models.sh
# Install latest ccache version # Install latest ccache version
RUN cget -p $PREFIX install facebook/zstd@v1.4.5 -X subdir -DCMAKE_DIR=build/cmake RUN cget -p $PREFIX install facebook/zstd@v1.4.5 -X subdir -DCMAKE_DIR=build/cmake
RUN cget -p $PREFIX install ccache@v4.1 -DENABLE_TESTING=OFF RUN cget -p $PREFIX install ccache@v4.1 -DENABLE_TESTING=OFF
RUN cget -p /opt/cmake install kitware/cmake@v3.24.3 RUN cget -p /opt/cmake install kitware/cmake@v3.26.4
COPY ./test/onnx/.onnxrt-commit / COPY ./test/onnx/.onnxrt-commit /
...@@ -115,7 +115,8 @@ ADD tools/build_and_install_onnxrt.sh /onnxruntime/build_and_install_onnxrt.sh ...@@ -115,7 +115,8 @@ ADD tools/build_and_install_onnxrt.sh /onnxruntime/build_and_install_onnxrt.sh
ADD tools/test_onnxrt_unit_tests.sh /onnxruntime/test_onnxrt_unit_tests.sh ADD tools/test_onnxrt_unit_tests.sh /onnxruntime/test_onnxrt_unit_tests.sh
ADD tools/test_onnxrt_parity_tests.sh /onnxruntime/test_onnxrt_parity_tests.sh ADD tools/test_onnxrt_parity_tests.sh /onnxruntime/test_onnxrt_parity_tests.sh
RUN cget -p /usr/local install ROCmSoftwarePlatform/rocMLIR@8d25af3b3721c159bb41cc6388e9453b1018c126 -DBUILD_MIXR_TARGET=On -DLLVM_ENABLE_ZSTD=Off -DLLVM_ENABLE_THREADS=Off # Use the /opt/cmake install because LLVM/MLIR need cmake >= 3.20
RUN env PATH=/opt/cmake/bin:$PATH cget -p /usr/local install ROCmSoftwarePlatform/rocMLIR@1ad9d6df32acc6d29d58e8ed6710e36746d0a4d6 -DBUILD_FAT_LIBROCKCOMPILER=On
ENV MIOPEN_FIND_DB_PATH=/tmp/miopen/find-db ENV MIOPEN_FIND_DB_PATH=/tmp/miopen/find-db
ENV MIOPEN_USER_DB_PATH=/tmp/miopen/user-db ENV MIOPEN_USER_DB_PATH=/tmp/miopen/user-db
......
...@@ -15,13 +15,11 @@ def rocmtestnode(Map conf) { ...@@ -15,13 +15,11 @@ def rocmtestnode(Map conf) {
def compiler = bconf.get("compiler", "/opt/rocm/llvm/bin/clang++") def compiler = bconf.get("compiler", "/opt/rocm/llvm/bin/clang++")
def flags = bconf.get("flags", "") def flags = bconf.get("flags", "")
def gpu_debug = bconf.get("gpu_debug", "0") def gpu_debug = bconf.get("gpu_debug", "0")
def hiprtc_workarounds = bconf.get("hiprtc_workarounds", "0")
def cmd = """ def cmd = """
ulimit -c unlimited ulimit -c unlimited
echo "leak:dnnl::impl::malloc" > suppressions.txt echo "leak:dnnl::impl::malloc" > suppressions.txt
export LSAN_OPTIONS="suppressions=\$(pwd)/suppressions.txt" export LSAN_OPTIONS="suppressions=\$(pwd)/suppressions.txt"
export MIGRAPHX_GPU_DEBUG=${gpu_debug} export MIGRAPHX_GPU_DEBUG=${gpu_debug}
export MIGRAPHX_ENABLE_HIPRTC_WORKAROUNDS=${hiprtc_workarounds}
export CXX=${compiler} export CXX=${compiler}
export CXXFLAGS='-Werror' export CXXFLAGS='-Werror'
env env
...@@ -90,9 +88,9 @@ def rocmnodename(name) { ...@@ -90,9 +88,9 @@ def rocmnodename(name) {
} else if(name == "navi21") { } else if(name == "navi21") {
node_name = "${rocmtest_name} && navi21"; node_name = "${rocmtest_name} && navi21";
} else if(name == "mi100+") { } else if(name == "mi100+") {
node_name = "${rocmtest_name} && (gfx908 || gfx90a)"; node_name = "${rocmtest_name} && (gfx908 || gfx90a) && !vm";
} else if(name == "anygpu") { } else if(name == "cdna") {
node_name = "${rocmtest_name} && (gfx908 || gfx90a || vega)"; node_name = "${rocmtest_name} && (gfx908 || gfx90a || vega) && !vm";
} else if(name == "nogpu") { } else if(name == "nogpu") {
node_name = "${rocmtest_name} && nogpu"; node_name = "${rocmtest_name} && nogpu";
} }
...@@ -105,35 +103,29 @@ def rocmnode(name, body) { ...@@ -105,35 +103,29 @@ def rocmnode(name, body) {
} }
} }
rocmtest clang_debug: rocmnode('vega') { cmake_build -> rocmtest clang_debug: rocmnode('cdna') { cmake_build ->
stage('Hip Clang Debug') { stage('hipRTC Debug') {
def sanitizers = "undefined" def sanitizers = "undefined"
def debug_flags = "-g -O2 -fsanitize=${sanitizers} -fno-sanitize-recover=${sanitizers}" def debug_flags = "-g -O2 -fsanitize=${sanitizers} -fno-sanitize-recover=${sanitizers}"
cmake_build(flags: "-DCMAKE_BUILD_TYPE=debug -DMIGRAPHX_ENABLE_PYTHON=Off -DCMAKE_CXX_FLAGS_DEBUG='${debug_flags}' -DCMAKE_C_FLAGS_DEBUG='${debug_flags}'") cmake_build(flags: "-DCMAKE_BUILD_TYPE=debug -DMIGRAPHX_ENABLE_PYTHON=Off -DCMAKE_CXX_FLAGS_DEBUG='${debug_flags}' -DCMAKE_C_FLAGS_DEBUG='${debug_flags}' -DMIGRAPHX_USE_HIPRTC=On", gpu_debug: true)
} }
}, clang_gpu_debug: rocmnode('vega') { cmake_build -> }, clang_release: rocmnode('cdna') { cmake_build ->
stage('Hip Clang GPU Debug') {
cmake_build(flags: "-DCMAKE_BUILD_TYPE=release", gpu_debug: true)
}
}, clang_release: rocmnode('vega') { cmake_build ->
stage('Hip Clang Release') { stage('Hip Clang Release') {
cmake_build(flags: "-DCMAKE_BUILD_TYPE=release") cmake_build(flags: "-DCMAKE_BUILD_TYPE=release")
stash includes: 'build/*.deb', name: 'migraphx-package' stash includes: 'build/*.deb', name: 'migraphx-package'
} }
}, hiprtc_gpu_debug: rocmnode('vega') { cmake_build -> }, all_targets_debug : rocmnode('cdna') { cmake_build ->
stage('HipRTC GPU Debug') {
cmake_build(flags: "-DCMAKE_BUILD_TYPE=release -DMIGRAPHX_USE_HIPRTC=On", gpu_debug: true, hiprtc_workarounds: true)
}
}, all_targets_debug : rocmnode('vega') { cmake_build ->
stage('All targets Release') { stage('All targets Release') {
cmake_build(flags: "-DCMAKE_BUILD_TYPE=release -DMIGRAPHX_ENABLE_GPU=On -DMIGRAPHX_ENABLE_CPU=On -DMIGRAPHX_ENABLE_FPGA=On") cmake_build(flags: "-DCMAKE_BUILD_TYPE=release -DMIGRAPHX_ENABLE_GPU=On -DMIGRAPHX_ENABLE_CPU=On -DMIGRAPHX_ENABLE_FPGA=On")
} }
}, mlir_debug: rocmnode('vega') { cmake_build -> }, mlir_debug: rocmnode('cdna') { cmake_build ->
stage('MLIR Debug') { stage('MLIR Debug') {
withEnv(['MIGRAPHX_ENABLE_MLIR=1']) { withEnv(['MIGRAPHX_ENABLE_MLIR=1']) {
def sanitizers = "undefined" def sanitizers = "undefined"
def debug_flags = "-g -O2 -fsanitize=${sanitizers} -fno-sanitize-recover=${sanitizers}" // Note: the -fno-sanitize= is copied from upstream LLVM_UBSAN_FLAGS.
cmake_build(flags: "-DCMAKE_BUILD_TYPE=debug -DMIGRAPHX_ENABLE_PYTHON=Off -DMIGRAPHX_ENABLE_MLIR=On -DCMAKE_CXX_FLAGS_DEBUG='${debug_flags}' -DCMAKE_C_FLAGS_DEBUG='${debug_flags}'") def debug_flags_cxx = "-g -O2 -fsanitize=${sanitizers} -fno-sanitize=vptr,function -fno-sanitize-recover=${sanitizers}"
def debug_flags = "-g -O2 -fsanitize=${sanitizers} -fno-sanitize=vptr -fno-sanitize-recover=${sanitizers}"
cmake_build(flags: "-DCMAKE_BUILD_TYPE=debug -DMIGRAPHX_ENABLE_PYTHON=Off -DMIGRAPHX_ENABLE_MLIR=On -DCMAKE_CXX_FLAGS_DEBUG='${debug_flags_cxx}' -DCMAKE_C_FLAGS_DEBUG='${debug_flags}'")
} }
} }
}, ck_release: rocmnode('mi100+') { cmake_build -> }, ck_release: rocmnode('mi100+') { cmake_build ->
...@@ -163,6 +155,7 @@ def onnxnode(name, body) { ...@@ -163,6 +155,7 @@ def onnxnode(name, body) {
} }
} }
rocmtest onnxbuild onnxnode('anygpu') { cmake_build -> rocmtest onnxbuild onnxnode('anygpu') { cmake_build ->
stage("Onnxruntime Build and Install") { stage("Onnxruntime Build and Install") {
sh ''' sh '''
......
...@@ -131,7 +131,7 @@ In this case, we can create `argument <migraphx::argument>` objects directly fro ...@@ -131,7 +131,7 @@ In this case, we can create `argument <migraphx::argument>` objects directly fro
std::vector<float> results_vector(64); std::vector<float> results_vector(64);
result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); }); result.visit([&](auto output) { results_vector.assign(output.begin(), output.end()); });
EXPECT(migraphx::verify_range(results_vector, sol)); EXPECT(migraphx::verify::verify_range(results_vector, sol));
An `argument <migraphx::argument>` can handle memory buffers from either the GPU or the CPU. An `argument <migraphx::argument>` can handle memory buffers from either the GPU or the CPU.
By default when running the `program <migraphx::program>`, buffers are allocated on the corresponding target. By default when running the `program <migraphx::program>`, buffers are allocated on the corresponding target.
......
...@@ -6,13 +6,12 @@ ARG PREFIX=/usr/local ...@@ -6,13 +6,12 @@ ARG PREFIX=/usr/local
RUN dpkg --add-architecture i386 RUN dpkg --add-architecture i386
# Add rocm repository # Add rocm repository
RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.5/ focal main > /etc/apt/sources.list.d/rocm.list' RUN sh -c 'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.6/ focal main > /etc/apt/sources.list.d/rocm.list'
# Install dependencies # Install dependencies
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-unauthenticated \
apt-utils \ apt-utils \
build-essential \ build-essential \
clang-format-10 \
cmake \ cmake \
curl \ curl \
doxygen \ doxygen \
......
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
google/protobuf@v3.11.0 -DCMAKE_POSITION_INDEPENDENT_CODE=On -X subdir -Dprotobuf_BUILD_TESTS=Off google/protobuf@v3.11.0 -DCMAKE_POSITION_INDEPENDENT_CODE=On -X subdir -Dprotobuf_BUILD_TESTS=Off
nlohmann/json@v3.8.0 nlohmann/json@v3.8.0
live-clones/blaze@v3.8 -X header -DHEADER_DIR=blaze -H sha256:d0ff011f47538285178908ea5f2cab46bb6a8f55b1edb6e03224a82dbc1a3212 live-clones/blaze@v3.8 -X header -DHEADER_DIR=blaze -H sha256:d0ff011f47538285178908ea5f2cab46bb6a8f55b1edb6e03224a82dbc1a3212
ROCmSoftwarePlatform/half@rocm-5.4.2 ROCmSoftwarePlatform/half@rocm-5.6.0
pybind/pybind11@d159a563383d10c821ba7b2a71905d1207db6de4 --build pybind/pybind11@d159a563383d10c821ba7b2a71905d1207db6de4 --build
msgpack/msgpack-c@cpp-3.3.0 -DMSGPACK_BUILD_TESTS=Off msgpack/msgpack-c@cpp-3.3.0 -DMSGPACK_BUILD_TESTS=Off
sqlite3@3.17 -DCMAKE_POSITION_INDEPENDENT_CODE=On sqlite3@3.17 -DCMAKE_POSITION_INDEPENDENT_CODE=On
......
...@@ -129,10 +129,11 @@ register_migraphx_ops( ...@@ -129,10 +129,11 @@ register_migraphx_ops(
contiguous contiguous
convert convert
convolution convolution
convolution_backwards
cosh cosh
cos cos
deconvolution
dequantizelinear dequantizelinear
dimensions_of
div div
dot dot
elu elu
......
...@@ -1487,13 +1487,17 @@ quantize_int8(const program& prog, const target& ptarget, const quantize_int8_op ...@@ -1487,13 +1487,17 @@ quantize_int8(const program& prog, const target& ptarget, const quantize_int8_op
struct experimental_custom_op_base struct experimental_custom_op_base
{ {
experimental_custom_op_base() = default;
experimental_custom_op_base(const experimental_custom_op_base&) = default;
experimental_custom_op_base& operator=(const experimental_custom_op_base&) = default;
virtual ~experimental_custom_op_base() = default;
virtual std::string name() const = 0; virtual std::string name() const = 0;
virtual argument compute(context ctx, shape output, arguments inputs) const = 0; virtual argument compute(context ctx, shape output, arguments inputs) const = 0;
virtual shape compute_shape(shapes inputs) const = 0; virtual shape compute_shape(shapes inputs) const = 0;
virtual std::vector<size_t> output_alias(shapes) const { return {}; } virtual std::vector<size_t> output_alias(shapes) const { return {}; }
// TODO: Return target string instead of bool // TODO: Return target string instead of bool
virtual bool runs_on_offload_target() const = 0; virtual bool runs_on_offload_target() const = 0;
virtual ~experimental_custom_op_base() = default;
}; };
struct experimental_custom_op : interface_base<MIGRAPHX_HANDLE_BASE(experimental_custom_op)> struct experimental_custom_op : interface_base<MIGRAPHX_HANDLE_BASE(experimental_custom_op)>
......
...@@ -150,8 +150,8 @@ insert_common_args(module& m, instruction_ref ins, std::vector<instruction_ref> ...@@ -150,8 +150,8 @@ insert_common_args(module& m, instruction_ref ins, std::vector<instruction_ref>
auto c_type = compute_common_types(input_shapes); auto c_type = compute_common_types(input_shapes);
auto c_dyn_dims = compute_common_dyn_dims(input_shapes); auto c_dyn_dims = compute_common_dyn_dims(input_shapes);
// following should work for a static or dynamic shape auto s0 = inputs[0]->get_shape();
if(inputs[0]->get_shape().dyn_dims() != c_dyn_dims) if(not s0.dynamic() or s0.dyn_dims() != c_dyn_dims)
{ {
inputs[0] = m.insert_instruction( inputs[0] = m.insert_instruction(
ins, make_op("multibroadcast", {{"out_dyn_dims", to_value(c_dyn_dims)}}), inputs); ins, make_op("multibroadcast", {{"out_dyn_dims", to_value(c_dyn_dims)}}), inputs);
...@@ -159,7 +159,8 @@ insert_common_args(module& m, instruction_ref ins, std::vector<instruction_ref> ...@@ -159,7 +159,8 @@ insert_common_args(module& m, instruction_ref ins, std::vector<instruction_ref>
std::transform(inputs.begin() + 1, inputs.end(), inputs.begin() + 1, [&](auto input) { std::transform(inputs.begin() + 1, inputs.end(), inputs.begin() + 1, [&](auto input) {
// uses previous input to avoid recalculating the common shape from the // uses previous input to avoid recalculating the common shape from the
// full set of input shapes at runtime // full set of input shapes at runtime
if(input->get_shape().dyn_dims() != c_dyn_dims) auto s = input->get_shape();
if(not s.dynamic() or s.dyn_dims() != c_dyn_dims)
{ {
return m.insert_instruction( return m.insert_instruction(
ins, ins,
......
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
namespace migraphx { namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS { inline namespace MIGRAPHX_INLINE_NS {
argument fill_argument(shape s, unsigned long value) argument fill_argument(shape s, double value)
{ {
argument result; argument result;
if(s.type() == shape::tuple_type) if(s.type() == shape::tuple_type)
......
...@@ -117,14 +117,14 @@ auto generate_tensor_data(const migraphx::shape& s, unsigned long seed = 0) ...@@ -117,14 +117,14 @@ auto generate_tensor_data(const migraphx::shape& s, unsigned long seed = 0)
} }
template <class T> template <class T>
auto fill_tensor_data(const migraphx::shape& s, unsigned long value = 0) auto fill_tensor_data(const migraphx::shape& s, double value = 0)
{ {
auto result = make_shared_array<T>(s.element_space()); auto result = make_shared_array<T>(s.element_space());
std::generate(result.get(), result.get() + s.element_space(), [=] { return value; }); std::generate(result.get(), result.get() + s.element_space(), [=] { return value; });
return result; return result;
} }
MIGRAPHX_EXPORT argument fill_argument(shape s, unsigned long value = 0); MIGRAPHX_EXPORT argument fill_argument(shape s, double value = 0);
MIGRAPHX_EXPORT argument generate_argument(shape s, unsigned long seed = 0); MIGRAPHX_EXPORT argument generate_argument(shape s, unsigned long seed = 0);
......
...@@ -43,7 +43,7 @@ template <class T, class... Ts> ...@@ -43,7 +43,7 @@ template <class T, class... Ts>
using dependent_type = typename select_dependent_type<T, Ts...>::type; using dependent_type = typename select_dependent_type<T, Ts...>::type;
MIGRAPHX_EXPORT MIGRAPHX_EXPORT
bool normalize_attributes(operation& op, const std::vector<std::size_t>& lens); bool normalize_attributes(operation& op, const shape& input_shape);
} // namespace MIGRAPHX_INLINE_NS } // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx } // namespace migraphx
......
...@@ -66,7 +66,19 @@ struct convert : unary<convert> ...@@ -66,7 +66,19 @@ struct convert : unary<convert>
auto type = target_type; auto type = target_type;
return [type](auto x) { return [type](auto x) {
auto y = x; auto y = x;
shape::visit(type, [&](auto as) { y = as(x); }); shape::visit(type, [&](auto as) {
// clamping value between target_type's max and min doesn't work for NaNs,
if(std::isnan(x))
{
y = as.nan();
}
else
{
// clamp overflowing/underflowing values to min()/max() instead of +/-infinity
// during downcasting
y = std::min(std::max(as(x), as.min()), as.max());
}
});
return y; return y;
}; };
} }
......
...@@ -79,17 +79,17 @@ struct convolution ...@@ -79,17 +79,17 @@ struct convolution
check_shapes{inputs, *this, true}.has(2).same_type().same_ndims().min_ndims(3); check_shapes{inputs, *this, true}.has(2).same_type().same_ndims().min_ndims(3);
check_attribute_size(); check_attribute_size();
// num of dims of input and attribute should match // num of dims of input and attribute should match
const auto input_size = inputs[0].max_lens().size(); const auto input_ndim = inputs[0].ndim();
const auto padding_size = padding.size(); const auto padding_size = padding.size();
if(input_size != padding_size / 2 + 2 && input_size != padding_size + 2) if(input_ndim != padding_size / 2 + 2 && input_ndim != padding_size + 2)
{ {
MIGRAPHX_THROW("CONVOLUTION: input and attribute size mismatch!"); MIGRAPHX_THROW("CONVOLUTION: input and attribute size mismatch!");
} }
const shape& x_shape = inputs.at(0); const shape& x_shape = inputs.at(0);
const shape& w_shape = inputs.at(1); const shape& w_shape = inputs.at(1);
const size_t num_spatial_dims = input_size - 2; const size_t num_spatial_dims = input_ndim - 2;
if(num_spatial_dims != this->kdims()) if(num_spatial_dims != this->kdims())
{ {
MIGRAPHX_THROW("CONVOLUTION: input k-dims does not match attribute size"); MIGRAPHX_THROW("CONVOLUTION: input k-dims does not match attribute size");
...@@ -105,7 +105,7 @@ struct convolution ...@@ -105,7 +105,7 @@ struct convolution
} }
else else
{ {
return fixed_compute_shape(x_shape, w_shape); return static_compute_shape(x_shape, w_shape);
} }
} }
...@@ -143,23 +143,10 @@ struct convolution ...@@ -143,23 +143,10 @@ struct convolution
shape dynamic_compute_shape(shape x_shape, shape w_shape) const shape dynamic_compute_shape(shape x_shape, shape w_shape) const
{ {
std::vector<shape::dynamic_dimension> output_dyn_dims = {}; std::vector<shape::dynamic_dimension> output_dyn_dims = {};
output_dyn_dims.push_back(x_shape.to_dynamic().dyn_dims().at(0));
output_dyn_dims.push_back(w_shape.to_dynamic().dyn_dims().at(0));
auto dynamic_shape_push_back = [&](const shape& input_shape) { const size_t num_spatial_dims = x_shape.ndim() - 2;
if(input_shape.dynamic())
{
output_dyn_dims.push_back(input_shape.dyn_dims().at(0));
}
else
{
auto l = input_shape.lens().at(0);
output_dyn_dims.push_back({l, l});
}
};
dynamic_shape_push_back(x_shape);
dynamic_shape_push_back(w_shape);
const size_t num_spatial_dims = x_shape.max_lens().size() - 2;
if(padding_mode != default_) if(padding_mode != default_)
{ {
for(std::size_t i = 0; i < num_spatial_dims; ++i) for(std::size_t i = 0; i < num_spatial_dims; ++i)
...@@ -198,7 +185,7 @@ struct convolution ...@@ -198,7 +185,7 @@ struct convolution
return shape{x_shape.type(), output_dyn_dims}; return shape{x_shape.type(), output_dyn_dims};
} }
shape fixed_compute_shape(shape x_shape, shape w_shape) const shape static_compute_shape(shape x_shape, shape w_shape) const
{ {
std::vector<size_t> output_lens{x_shape.lens()[0], w_shape.lens()[0]}; std::vector<size_t> output_lens{x_shape.lens()[0], w_shape.lens()[0]};
auto spatial_lens = calc_conv_lens(x_shape.lens(), w_shape.lens()); auto spatial_lens = calc_conv_lens(x_shape.lens(), w_shape.lens());
......
...@@ -21,9 +21,11 @@ ...@@ -21,9 +21,11 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE. * THE SOFTWARE.
*/ */
#ifndef MIGRAPHX_GUARD_OPERATORS_DECONVOLUTION_HPP #ifndef MIGRAPHX_GUARD_OPERATORS_CONVOLUTION_BACKWARDS_HPP
#define MIGRAPHX_GUARD_OPERATORS_DECONVOLUTION_HPP #define MIGRAPHX_GUARD_OPERATORS_CONVOLUTION_BACKWARDS_HPP
#include <cmath>
#include <utility>
#include <migraphx/op/common.hpp> #include <migraphx/op/common.hpp>
#include <migraphx/check_shapes.hpp> #include <migraphx/check_shapes.hpp>
#include <migraphx/config.hpp> #include <migraphx/config.hpp>
...@@ -31,14 +33,13 @@ ...@@ -31,14 +33,13 @@
#include <migraphx/argument.hpp> #include <migraphx/argument.hpp>
#include <migraphx/par_dfor.hpp> #include <migraphx/par_dfor.hpp>
#include <migraphx/shape_for_each.hpp> #include <migraphx/shape_for_each.hpp>
#include <cmath> #include <migraphx/dyn_output.hpp>
#include <utility>
namespace migraphx { namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS { inline namespace MIGRAPHX_INLINE_NS {
namespace op { namespace op {
struct deconvolution struct convolution_backwards
{ {
std::vector<std::size_t> padding = {0, 0}; std::vector<std::size_t> padding = {0, 0};
std::vector<std::size_t> stride = {1, 1}; std::vector<std::size_t> stride = {1, 1};
...@@ -57,45 +58,91 @@ struct deconvolution ...@@ -57,45 +58,91 @@ struct deconvolution
f(self.group, "group")); f(self.group, "group"));
} }
std::string name() const { return "deconvolution"; } std::string name() const { return "convolution_backwards"; }
void check_attribute_size() const void check_attribute_size() const
{ {
if((padding.size() != stride.size() and (padding.size() / 2) != stride.size()) or if(padding.size() != stride.size() or stride.size() != dilation.size())
stride.size() != dilation.size())
{ {
MIGRAPHX_THROW("deconvolution: inconsistent attribute sizes"); MIGRAPHX_THROW("CONVOLUTION_BACKWARDS: inconsistent attribute sizes");
} }
} }
shape compute_shape(std::vector<shape> inputs) const shape compute_shape(std::vector<shape> inputs) const
{ {
check_shapes{inputs, *this}.has(2).same_type().same_ndims().min_ndims(3); check_shapes{inputs, *this, true}.has(2).same_type().same_ndims().min_ndims(3);
const shape& input = inputs.at(0); const shape& x_shape = inputs.at(0);
const shape& weights = inputs.at(1); const shape& w_shape = inputs.at(1);
size_t kdims = input.lens().size() - 2; if(x_shape.ndim() - 2 != this->kdims())
if(kdims != this->kdims())
{ {
MIGRAPHX_THROW("deconvolution: input k-dims does not match attribute size"); MIGRAPHX_THROW("CONVOLUTION_BACKWARDS: input k-dims does not match attribute size");
} }
std::vector<size_t> output_lens{input.lens()[0], weights.lens()[1]}; if(not x_shape.dynamic() and not w_shape.dynamic() and
x_shape.lens().at(1) != (w_shape.lens().at(0) * group))
{
MIGRAPHX_THROW("CONVOLUTION_BACKWARDS: mismatched channel numbers");
}
for(size_t i = 0; i < kdims; i++) if(x_shape.dynamic() or w_shape.dynamic())
{ {
output_lens.push_back(std::size_t(std::max<std::ptrdiff_t>( return dynamic_compute_shape(x_shape, w_shape);
}
else
{
return static_compute_shape(x_shape, w_shape);
}
}
std::vector<std::size_t> calc_spatial_lens(std::vector<std::size_t> x_lens,
std::vector<std::size_t> w_lens) const
{
std::vector<size_t> spatial_lens(x_lens.size() - 2);
// stride * (input - 1) + output_padding + ((kernel - 1) * dilation + 1) - padding_L -
// padding_R. This assumes padding_L = padding_R and output_padding handled in parser.
for(size_t i = 0; i < spatial_lens.size(); i++)
{
spatial_lens.at(i) = (std::size_t(std::max<std::ptrdiff_t>(
1, 1,
stride[i] * (input.lens()[i + 2] - 1) + stride[i] * (x_lens[i + 2] - 1) + ((w_lens[i + 2] - 1) * dilation[i] + 1) -
((weights.lens()[i + 2] - 1) * dilation[i] + 1) - 2 * padding[i]))); 2 * padding[i])));
} }
return inputs[0].with_lens(output_lens); return spatial_lens;
}
shape dynamic_compute_shape(shape x_shape, shape w_shape) const
{
std::vector<shape::dynamic_dimension> output_dyn_dims = {};
output_dyn_dims.push_back(x_shape.to_dynamic().dyn_dims().at(0));
output_dyn_dims.push_back(w_shape.to_dynamic().dyn_dims().at(1));
const std::size_t num_spatial_dims = x_shape.ndim() - 2;
// Does not compute for optimals
auto min_spatial_dims = calc_spatial_lens(x_shape.min_lens(), w_shape.min_lens());
auto max_spatial_dims = calc_spatial_lens(x_shape.max_lens(), w_shape.max_lens());
for(size_t i = 0; i < num_spatial_dims; ++i)
{
output_dyn_dims.push_back(
shape::dynamic_dimension{min_spatial_dims[i], max_spatial_dims[i], {}});
}
return shape{x_shape.type(), output_dyn_dims};
}
shape static_compute_shape(shape x_shape, shape w_shape) const
{
std::vector<size_t> output_lens{x_shape.lens()[0], w_shape.lens()[1]};
auto spatial_lens = calc_spatial_lens(x_shape.lens(), w_shape.lens());
std::for_each(spatial_lens.begin(), spatial_lens.end(), [&output_lens](auto x) {
output_lens.push_back(x);
});
return x_shape.with_lens(output_lens);
} }
argument compute(shape output_shape, std::vector<argument> args) const argument compute(const dyn_output& dyn_out, std::vector<argument> args) const
{ {
argument result{output_shape}; argument result{dyn_out.computed_shape};
auto kdims = this->kdims(); auto num_spatial_dims = this->kdims();
visit_all(result, args[0], args[1])([&](auto output, auto input, auto weights) { visit_all(result, args[0], args[1])([&](auto output, auto input, auto weights) {
using type = typename decltype(output)::value_type; using type = typename decltype(output)::value_type;
...@@ -109,22 +156,22 @@ struct deconvolution ...@@ -109,22 +156,22 @@ struct deconvolution
auto wei_n = wei[0]; auto wei_n = wei[0];
auto wei_c = wei[1]; auto wei_c = wei[1];
auto out_lens = output_shape.lens(); auto out_lens = dyn_out.computed_shape.lens();
std::vector<std::size_t> win_size{in_c}; std::vector<std::size_t> win_size{in_c};
std::copy(in_lens.begin() + 2, in_lens.end(), std::back_inserter(win_size)); std::copy(in_lens.begin() + 2, in_lens.end(), std::back_inserter(win_size));
std::copy(wei.begin() + 2, wei.end(), std::back_inserter(win_size)); std::copy(wei.begin() + 2, wei.end(), std::back_inserter(win_size));
shape win_shape{output_shape.type(), win_size}; shape win_shape{dyn_out.computed_shape.type(), win_size};
par_dfor(in_n, wei_c)([&](int o, int k) { par_dfor(in_n, wei_c)([&](int o, int k) {
shape_for_each(win_shape, [&](auto idx_win) { shape_for_each(win_shape, [&](auto idx_win) {
const int w = idx_win[0]; const int w = idx_win[0];
auto input_dims_start = idx_win.begin() + 1; auto input_dims_start = idx_win.begin() + 1;
auto wei_dims_start = idx_win.begin() + kdims + 1; auto wei_dims_start = idx_win.begin() + num_spatial_dims + 1;
std::vector<std::ptrdiff_t> win_start; std::vector<std::ptrdiff_t> win_start;
for(std::size_t n = 0; n < kdims; ++n) for(std::size_t n = 0; n < num_spatial_dims; ++n)
{ {
win_start.push_back(std::ptrdiff_t(*(input_dims_start + n) * stride[n]) - win_start.push_back(std::ptrdiff_t(*(input_dims_start + n) * stride[n]) -
std::ptrdiff_t(padding[n])); std::ptrdiff_t(padding[n]));
...@@ -135,7 +182,7 @@ struct deconvolution ...@@ -135,7 +182,7 @@ struct deconvolution
std::vector<std::ptrdiff_t> idx_out{o, in_ch}; std::vector<std::ptrdiff_t> idx_out{o, in_ch};
for(size_t n = 0; n < kdims; n++) for(size_t n = 0; n < num_spatial_dims; n++)
{ {
idx_out.push_back(win_start[n] + *(wei_dims_start + n) * dilation[n]); idx_out.push_back(win_start[n] + *(wei_dims_start + n) * dilation[n]);
} }
......
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-2023 Advanced Micro Devices, Inc. All rights reserved.
*
* 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.
*/
#ifndef MIGRAPHX_GUARD_OPERATORS_DIMENSIONS_OF_HPP
#define MIGRAPHX_GUARD_OPERATORS_DIMENSIONS_OF_HPP
#include <migraphx/check_shapes.hpp>
#include <migraphx/argument.hpp>
#include <migraphx/dyn_output.hpp>
namespace migraphx {
inline namespace MIGRAPHX_INLINE_NS {
namespace op {
/**
* Returns the dimensions of the input argument from starting axis to ending axis.
* Atleast `end` must be set to use this operator (set `end` to ndim for default ONNX behavior of
* `Shape` operator) This should only be used for dynamic shapes as this can be simplified to a
* literal for static shapes.
*/
struct dimensions_of
{
std::size_t start = 0;
std::size_t end = 0;
template <class Self, class F>
static auto reflect(Self& self, F f)
{
return pack(f(self.start, "start"), f(self.end, "end"));
}
std::string name() const { return "dimensions_of"; }
shape compute_shape(const std::vector<shape>& inputs) const
{
check_shapes{inputs, *this, true}.has(1);
if(start >= end)
{
MIGRAPHX_THROW("DIMENSIONS_OF: start >= end. start = " + std::to_string(start) +
", end = " + std::to_string(end));
}
return shape{shape::int64_type, {end - start}};
}
argument compute(const shape& output_shape, std::vector<argument> args) const
{
argument result{output_shape};
auto input_lens = args[0].get_shape().lens();
result.visit([&](auto output) {
std::copy(input_lens.cbegin() + start, input_lens.cbegin() + end, output.begin());
});
return result;
}
};
} // namespace op
} // namespace MIGRAPHX_INLINE_NS
} // namespace migraphx
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment