Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
gaoqiong
MIGraphX
Commits
c9497134
Commit
c9497134
authored
Feb 15, 2023
by
charlie
Browse files
Merge branch 'develop' of github.com:ROCmSoftwarePlatform/AMDMIGraphX into select_module_op
parents
e833a916
67f23675
Changes
81
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
470 additions
and
122 deletions
+470
-122
.clang-tidy
.clang-tidy
+2
-0
.github/workflows/ci.yaml
.github/workflows/ci.yaml
+4
-3
.github/workflows/history.yaml
.github/workflows/history.yaml
+30
-0
.github/workflows/performance.yaml
.github/workflows/performance.yaml
+4
-4
.github/workflows/sync-onnxrt-main.yaml
.github/workflows/sync-onnxrt-main.yaml
+46
-0
Dockerfile
Dockerfile
+30
-8
Jenkinsfile
Jenkinsfile
+6
-0
hip-clang.docker
hip-clang.docker
+1
-1
src/CMakeLists.txt
src/CMakeLists.txt
+2
-2
src/include/migraphx/check_shapes.hpp
src/include/migraphx/check_shapes.hpp
+18
-1
src/include/migraphx/half.hpp
src/include/migraphx/half.hpp
+2
-2
src/include/migraphx/instruction_ref.hpp
src/include/migraphx/instruction_ref.hpp
+2
-2
src/include/migraphx/match/layernorm.hpp
src/include/migraphx/match/layernorm.hpp
+30
-6
src/include/migraphx/memory_coloring.hpp
src/include/migraphx/memory_coloring.hpp
+1
-1
src/include/migraphx/op/concat.hpp
src/include/migraphx/op/concat.hpp
+64
-25
src/include/migraphx/op/gather.hpp
src/include/migraphx/op/gather.hpp
+40
-15
src/include/migraphx/op/gathernd.hpp
src/include/migraphx/op/gathernd.hpp
+88
-17
src/include/migraphx/op/normalize_attribute.hpp
src/include/migraphx/op/normalize_attribute.hpp
+21
-9
src/include/migraphx/op/scatternd_op.hpp
src/include/migraphx/op/scatternd_op.hpp
+66
-21
src/include/migraphx/op/where.hpp
src/include/migraphx/op/where.hpp
+13
-5
No files found.
.clang-tidy
View file @
c9497134
...
...
@@ -9,6 +9,8 @@ CheckOptions:
value: risky
- key: modernize-loop-convert.NamingStyle
value: lower_case
- key: misc-const-correctness.AnalyzeValues
value: 'false'
- key: performance-unnecessary-copy-initialization.AllowedTypes
value: 'shape'
- key: performance-unnecessary-value-param.AllowedTypes
...
...
.github/workflows/ci.yaml
View file @
c9497134
...
...
@@ -32,7 +32,8 @@ jobs:
# In this step, this action saves a list of existing images,
# the cache is created without them in the post run.
# It also restores the cache if it exists.
-
uses
:
satackey/action-docker-layer-caching@v0.0.11
# name: Docker Layer Caching2
-
uses
:
jpribyl/action-docker-layer-caching@v0.1.1
# Ignore the failure of a step and avoid terminating the job.
continue-on-error
:
true
...
...
@@ -81,7 +82,7 @@ jobs:
# In this step, this action saves a list of existing images,
# the cache is created without them in the post run.
# It also restores the cache if it exists.
-
uses
:
satackey
/action-docker-layer-caching@v0.
0
.1
1
-
uses
:
jpribyl
/action-docker-layer-caching@v0.
1
.1
# Ignore the failure of a step and avoid terminating the job.
continue-on-error
:
true
...
...
@@ -126,7 +127,7 @@ jobs:
# In this step, this action saves a list of existing images,
# the cache is created without them in the post run.
# It also restores the cache if it exists.
-
uses
:
satackey
/action-docker-layer-caching@v0.
0
.1
1
-
uses
:
jpribyl
/action-docker-layer-caching@v0.
1
.1
# Ignore the failure of a step and avoid terminating the job.
continue-on-error
:
true
...
...
.github/workflows/history.yaml
0 → 100644
View file @
c9497134
name
:
History
on
:
workflow_dispatch
:
inputs
:
start_date
:
description
:
Start date for results analysis
required
:
true
default
:
'
yyyy-mm-dd'
end_date
:
description
:
End date for results analysis
required
:
true
default
:
'
yyyy-mm-dd'
history_repo
:
description
:
Repository for history results between dates
required
:
true
default
:
'
ROCmSoftwarePlatform/migraphx-reports'
jobs
:
release
:
uses
:
migraphx-benchmark/actions/.github/workflows/history.yml@main
with
:
start_date
:
${{ github.event.inputs.start_date || 'yyyy-mm-dd' }}
end_date
:
${{ github.event.inputs.end_date || 'yyyy-mm-dd' }}
history_repo
:
${{ github.event.inputs.history_repo || 'ROCmSoftwarePlatform/migraphx-reports' }}
secrets
:
gh_token
:
${{ secrets.MIGRAPHX_BOT_TOKEN }}
mail_user
:
${{ secrets.MAIL_USERNAME }}
mail_pass
:
${{ secrets.MAIL_PASSWORD }}
.github/workflows/performance.yaml
View file @
c9497134
...
...
@@ -12,7 +12,7 @@ on:
rocm_release
:
description
:
ROCm Version
required
:
true
default
:
'
5.
3
'
default
:
'
5.
4.2
'
performance_reports_repo
:
description
:
Result repository
required
:
true
...
...
@@ -24,7 +24,7 @@ on:
flags
:
description
:
-m for Max value; -s for Std dev; -r for Threshold file
required
:
true
default
:
'
-
s
'
default
:
'
-
r
'
concurrency
:
"
perftest-${{
github.head_ref
||
github.base_ref
||
'schedule'
}}"
...
...
@@ -32,9 +32,9 @@ jobs:
release
:
uses
:
ROCmSoftwarePlatform/migraphx-benchmark/.github/workflows/perf-test.yml@main
with
:
rocm_release
:
${{ github.event.inputs.rocm_release || '5.
3
' }}
rocm_release
:
${{ github.event.inputs.rocm_release || '5.
4.2
' }}
result_number
:
${{ github.event.inputs.result_number || '10' }}
flags
:
${{ github.event.inputs.flags || '-
s
' }}
flags
:
${{ github.event.inputs.flags || '-
r
' }}
performance_reports_repo
:
${{ github.event.inputs.performance_reports_repo || 'ROCmSoftwarePlatform/migraphx-reports' }}
secrets
:
gh_token
:
${{ secrets.MIGRAPHX_BOT_TOKEN }}
...
...
.github/workflows/sync-onnxrt-main.yaml
0 → 100644
View file @
c9497134
name
:
Onnxruntime main weekly sync
on
:
schedule
:
-
cron
:
"
05
17
*
*
1"
jobs
:
runs-on
:
ubuntu-latest
sync
:
steps
:
-
uses
:
actions/checkout@v3
with
:
ref
:
develop
path
:
../
get_date
:
steps
:
-
run
:
echo "::set-output name=date::$(date +'%Y-%m-%d')"
update_file
:
needs
:
[
sync get_date
]
steps
:
-
run
:
git clone https://github.com/microsoft/onnxruntime.git && cd onnxruntime && git rev-parse HEAD >> ../test/onnx/.onnxrt-commit
Add_commit
:
needs
:
update_file
steps
:
-
name
:
Add & Commit
uses
:
EndBug/add-and-commit@v9.1.1
with
:
new_branch
:
onnxruntime-sync-${{ steps.date.outputs.date }}
add
:
../test/onnx/.onnxrt-commit
message
:
Update Onnxruntime commit to latest release
default_author
:
github_actions
push
:
true
PR
:
needs
:
Add_commit
steps
:
-
name
:
GitHub Action for creating Pull Requests
uses
:
devops-infra/action-pull-request@v0.5.3
with
:
github_token
:
${{ secrets.GITHUB_TOKEN }}
title
:
Sync Onnxruntime main
reviewer
:
pfultz2, causten
assignee
:
TedThemistokleous
label
:
automatic, onnxruntime
target_branch
:
develop
Dockerfile
View file @
c9497134
...
...
@@ -5,8 +5,12 @@ ARG PREFIX=/usr/local
# Support multiarch
RUN
dpkg
--add-architecture
i386
# Install rocm key
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 -
# Add rocm repository
RUN
sh
-c
'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.
3
/ ubuntu main > /etc/apt/sources.list.d/rocm.list'
RUN
sh
-c
'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.
4.2
/ ubuntu main > /etc/apt/sources.list.d/rocm.list'
# Install dependencies
RUN
apt-get update
&&
DEBIAN_FRONTEND
=
noninteractive apt-get
install
-y
--allow-unauthenticated
\
...
...
@@ -32,10 +36,27 @@ RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --allow-
libnuma-dev
\
miopen-hip
\
rocblas
\
hipfft
\
rocthrust
\
rocrand
\
hipsparse
\
rccl
\
rccl-dev
\
rocm-smi-lib
\
rocm-dev
\
roctracer-dev
\
hipcub
\
hipblas
\
hipify-clang
\
half
\
libssl-dev
\
zlib1g-dev
&&
\
apt-get clean
&&
\
rm
-rf
/var/lib/apt/lists/
*
# add this for roctracer dependancies
RUN
pip3
install
CppHeaderParser
packaging
==
22.0
# Workaround broken rocm packages
RUN
ln
-s
/opt/rocm-
*
/opt/rocm
RUN
echo
"/opt/rocm/lib"
>
/etc/ld.so.conf.d/rocm.conf
...
...
@@ -65,25 +86,26 @@ ADD doc/requirements.txt /doc-requirements.txt
RUN
pip3
install
-r
/doc-requirements.txt
# Download real models to run onnx unit tests
ENV
ONNX_HOME=
$HOME
ENV
ONNX_HOME=
/.onnx
COPY
./tools/download_models.sh /
RUN
/download_models.sh
&&
rm
/download_models.sh
# 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
ccache@v4.1
-DENABLE_TESTING
=
OFF
RUN
cget
-p
/opt/cmake
install
kitware/cmake@v3.24.3
# Install newer cmake for onnx runtime
ARG
CMAKE_VERSION=3.24.2
RUN
cget
-p
/opt/cmake
install
-X
binary https://github.com/Kitware/CMake/releases/download/v
${
CMAKE_VERSION
}
/cmake-
${
CMAKE_VERSION
}
-Linux-x86_64
.tar.gz
COPY
./test/onnx/.onnxrt-commit /
ARG
ONNXRUNTIME_REPO=https://github.com/Microsoft/onnxruntime
ARG
ONNXRUNTIME_BRANCH=main
ARG
ONNXRUNTIME_COMMIT=24f1bd6156cf5968bbc76dfb0e801a9b9c56b9fc
ARG
ONNXRUNTIME_COMMIT
RUN
git clone
--single-branch
--branch
${
ONNXRUNTIME_BRANCH
}
--recursive
${
ONNXRUNTIME_REPO
}
onnxruntime
&&
\
cd
onnxruntime
&&
\
git checkout
${
ONNXRUNTIME_COMMIT
}
&&
\
/bin/sh dockerfiles/scripts/install_common_deps.sh
if
[
-z
"
$ONNXRUNTIME_COMMIT
"
]
;
then
git checkout
$(
cat
/.onnxrt-commit
)
;
else
git checkout
${
ONNXRUNTIME_COMMIT
}
;
fi
&&
\
/bin/sh /onnxruntime/dockerfiles/scripts/install_common_deps.sh
ADD
tools/build_and_test_onnxrt.sh /onnxruntime/build_and_test_onnxrt.sh
...
...
Jenkinsfile
View file @
c9497134
...
...
@@ -15,11 +15,13 @@ def rocmtestnode(Map conf) {
def
compiler
=
bconf
.
get
(
"compiler"
,
"/opt/rocm/llvm/bin/clang++"
)
def
flags
=
bconf
.
get
(
"flags"
,
""
)
def
gpu_debug
=
bconf
.
get
(
"gpu_debug"
,
"0"
)
def
hiprtc_workarounds
=
bconf
.
get
(
"hiprtc_workarounds"
,
"0"
)
def
cmd
=
"""
ulimit -c unlimited
echo "leak:dnnl::impl::malloc" > suppressions.txt
export LSAN_OPTIONS="suppressions=\$(pwd)/suppressions.txt"
export MIGRAPHX_GPU_DEBUG=${gpu_debug}
export MIGRAPHX_ENABLE_HIPRTC_WORKAROUNDS=${hiprtc_workarounds}
export CXX=${compiler}
export CXXFLAGS='-Werror'
env
...
...
@@ -110,6 +112,10 @@ rocmtest clang_debug: rocmnode('vega') { cmake_build ->
cmake_build
(
flags:
"-DCMAKE_BUILD_TYPE=release"
)
stash
includes:
'build/*.deb'
,
name:
'migraphx-package'
}
},
hiprtc_gpu_debug:
rocmnode
(
'vega'
)
{
cmake_build
->
stage
(
'HipRTC GPU Debug'
)
{
cmake_build
(
flags:
"-DCMAKE_BUILD_TYPE=release -DMIGRAPHX_USE_HIPRTC=On"
,
gpu_debug:
true
,
hiprtc_workarounds:
true
)
}
},
mlir_debug:
rocmnode
(
'vega'
)
{
cmake_build
->
stage
(
'MLIR Debug'
)
{
def
sanitizers
=
"undefined"
...
...
hip-clang.docker
View file @
c9497134
...
...
@@ -6,7 +6,7 @@ ARG PREFIX=/usr/local
RUN
dpkg
--add-architecture
i386
# Add rocm repository
RUN
sh
-c
'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.
3
/ ubuntu main > /etc/apt/sources.list.d/rocm.list'
RUN
sh
-c
'echo deb [arch=amd64 trusted=yes] http://repo.radeon.com/rocm/apt/5.
4.2
/ ubuntu main > /etc/apt/sources.list.d/rocm.list'
# Install dependencies
RUN
apt-get update
&&
DEBIAN_FRONTEND
=
noninteractive apt-get
install
-y
--allow-unauthenticated
\
...
...
src/CMakeLists.txt
100755 → 100644
View file @
c9497134
...
...
@@ -58,14 +58,14 @@ add_library(migraphx
layout_nhwc.cpp
load_save.cpp
make_op.cpp
memory_coloring.cpp
module.cpp
msgpack.cpp
normalize_attributes.cpp
normalize_ops.cpp
op_enums.cpp
operation.cpp
opt/memory_coloring.cpp
opt/memory_coloring_impl.cpp
optimize_module.cpp
pad_calc.cpp
pass_manager.cpp
permutation.cpp
...
...
src/include/migraphx/check_shapes.hpp
View file @
c9497134
...
...
@@ -87,7 +87,7 @@ struct check_shapes
}
/*!
*
Check if
the number of shape objects
is
equal to
atleast
one of the
*
Require
the number of shape objects
to
equal to one of the
* given sizes.
* \param ns template parameter pack of sizes to check against
*/
...
...
@@ -100,6 +100,23 @@ struct check_shapes
return
*
this
;
}
/*!
* Require the number of shape objects to equal at least a given amount. Use this
* method for ops that can take any number (variadic) of inputs.
* \param n min. number of shapes
*/
const
check_shapes
&
has_at_least
(
std
::
size_t
n
)
const
{
if
(
this
->
size
()
<
n
)
MIGRAPHX_THROW
(
prefix
()
+
"Wrong number of arguments: expected at least "
+
to_string
(
n
)
+
" but given "
+
std
::
to_string
(
size
()));
return
*
this
;
}
/*!
* Require all shapes to have the same number of elements.
* \param n number of
*/
const
check_shapes
&
nelements
(
std
::
size_t
n
)
const
{
if
(
not
this
->
all_of
([
&
](
const
shape
&
s
)
{
return
s
.
elements
()
==
n
;
}))
...
...
src/include/migraphx/half.hpp
View file @
c9497134
...
...
@@ -58,12 +58,12 @@ using deduce = typename detail::deduce<T>::type;
namespace
std
{
template
<
class
T
>
struct
common_type
<
migraphx
::
half
,
T
>
:
std
::
common_type
<
float
,
T
>
struct
common_type
<
migraphx
::
half
,
T
>
:
std
::
common_type
<
float
,
T
>
// NOLINT
{
};
template
<
class
T
>
struct
common_type
<
T
,
migraphx
::
half
>
:
std
::
common_type
<
float
,
T
>
struct
common_type
<
T
,
migraphx
::
half
>
:
std
::
common_type
<
float
,
T
>
// NOLINT
{
};
...
...
src/include/migraphx/instruction_ref.hpp
View file @
c9497134
...
...
@@ -41,7 +41,7 @@ migraphx::instruction* as_address(const instruction_ref& ins) noexcept;
namespace
std
{
template
<
>
struct
hash
<
migraphx
::
instruction_ref
>
struct
hash
<
migraphx
::
instruction_ref
>
// NOLINT
{
using
argument_type
=
migraphx
::
instruction_ref
;
using
result_type
=
std
::
size_t
;
...
...
@@ -52,7 +52,7 @@ struct hash<migraphx::instruction_ref>
};
template
<
>
struct
equal_to
<
migraphx
::
instruction_ref
>
struct
equal_to
<
migraphx
::
instruction_ref
>
// NOLINT
{
using
argument_type
=
migraphx
::
instruction_ref
;
using
result_type
=
bool
;
...
...
src/include/migraphx/match/layernorm.hpp
View file @
c9497134
...
...
@@ -36,22 +36,46 @@ template <class F>
struct
layernorm_matcher
{
F
f
;
auto
last_axis
()
const
{
return
make_basic_pred_matcher
([](
instruction_ref
ins
)
{
auto
v
=
ins
->
get_operator
().
to_value
();
if
(
not
v
.
contains
(
"axes"
))
return
false
;
auto
axes
=
v
[
"axes"
].
to_vector
<
std
::
size_t
>
();
if
(
axes
.
size
()
!=
1
)
return
false
;
return
axes
.
front
()
==
ins
->
inputs
().
front
()
->
get_shape
().
lens
().
size
()
-
1
;
});
}
auto
reduce_mean
()
const
{
return
f
(
"reduce_mean"
)(
last_axis
());
}
auto
x_minus_mean
()
const
{
return
f
(
"sub"
)(
arg
(
0
)(
any
().
bind
(
"x"
)),
arg
(
1
)(
skip_broadcasts
(
f
(
"
reduce_mean
"
))));
return
f
(
"sub"
)(
arg
(
0
)(
any
().
bind
(
"x"
)),
arg
(
1
)(
skip_broadcasts
(
reduce_mean
(
))));
}
auto
variance
()
const
{
return
f
(
"reduce_mean"
)(
arg
(
0
)(
f
(
"pow"
)(
arg
(
0
)(
x_minus_mean
()),
arg
(
1
)(
has_value
(
2.0
f
)))));
return
reduce_mean
()(
arg
(
0
)(
any_of
(
f
(
"pow"
)(
arg
(
0
)(
x_minus_mean
()),
arg
(
1
)(
has_value
(
2.0
f
))),
f
(
"mul"
)(
arg
(
0
)(
x_minus_mean
()),
arg
(
1
)(
x_minus_mean
())),
f
(
"sqdiff"
)(
either_arg
(
0
,
1
)(
any
().
bind
(
"x"
),
skip_broadcasts
(
reduce_mean
()))))));
}
auto
layernorm_onnx
(
)
const
auto
sqrt_add_eps
(
const
std
::
string
&
name
)
const
{
return
f
(
"div"
)(
arg
(
0
)(
x_minus_mean
()),
auto
add_eps
=
f
(
"add"
)(
either_arg
(
0
,
1
)(
variance
(),
is_constant
().
bind
(
"eps"
)));
return
skip_broadcasts
(
f
(
name
)(
arg
(
0
)(
any_of
(
add_eps
,
variance
()))));
}
arg
(
1
)(
skip_broadcasts
(
f
(
"sqrt"
)(
arg
(
0
)(
f
(
"add"
)(
either_arg
(
0
,
1
)(
variance
(),
is_constant
().
bind
(
"eps"
))))))));
auto
layernorm_onnx
()
const
{
auto
div_sqrt
=
f
(
"div"
)(
arg
(
0
)(
x_minus_mean
()),
arg
(
1
)(
sqrt_add_eps
(
"sqrt"
)));
auto
mul_rsqrt
=
f
(
"mul"
)(
either_arg
(
0
,
1
)(
x_minus_mean
(),
sqrt_add_eps
(
"rsqrt"
)));
return
any
(
any_of
(
div_sqrt
,
mul_rsqrt
));
}
auto
matcher
()
const
{
return
layernorm_onnx
();
}
...
...
src/include/migraphx/memory_coloring.hpp
View file @
c9497134
...
...
@@ -39,7 +39,7 @@ struct memory_coloring
{
std
::
string
allocation_op
{};
bool
verify
=
false
;
std
::
string
name
()
const
{
return
"memory
coloring"
;
}
std
::
string
name
()
const
{
return
"memory
_
coloring"
;
}
void
apply
(
module
&
m
)
const
;
};
...
...
src/include/migraphx/op/concat.hpp
View file @
c9497134
...
...
@@ -26,6 +26,7 @@
#include <array>
#include <migraphx/check_shapes.hpp>
#include <migraphx/dyn_output.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/streamutils.hpp>
#include <migraphx/literal.hpp>
...
...
@@ -73,49 +74,87 @@ struct concat
}
return
offsets
;
}
shape
normalize_compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
if
(
inputs
.
empty
())
// inputs can contain 1 or more shapes (variadic). compute_shape_op ensures there must
// be at least 1.
check_shapes
{
inputs
,
*
this
,
true
}.
same_ndims
().
same_type
();
if
(
std
::
none_of
(
inputs
.
begin
(),
inputs
.
end
(),
[
&
](
const
shape
&
s
)
{
return
s
.
dynamic
();
}))
{
MIGRAPHX_THROW
(
"CONCAT: Number of input tensors should exceed 0"
);
// Static input shapes
const
auto
&
first_shape_lens
=
inputs
.
front
().
lens
();
const
auto
&
type
=
inputs
.
front
().
type
();
for
(
std
::
size_t
ll
=
0
;
ll
<
first_shape_lens
.
size
();
ll
++
)
{
if
(
ll
!=
axis
)
{
if
(
not
std
::
all_of
(
inputs
.
begin
(),
inputs
.
end
(),
[
&
](
auto
s
)
{
return
s
.
lens
()[
ll
]
==
first_shape_lens
[
ll
];
}))
{
MIGRAPHX_THROW
(
"CONCAT: all input dimensions should match along axis "
+
std
::
to_string
(
ll
));
}
}
}
std
::
size_t
new_dim_axis
=
0
;
for
(
const
auto
&
input
:
inputs
)
{
const
auto
&
lens
=
input
.
lens
();
new_dim_axis
+=
lens
[
axis
];
}
std
::
vector
<
std
::
size_t
>
new_lens
=
first_shape_lens
;
new_lens
[
axis
]
=
new_dim_axis
;
return
shape
::
from_permutation
(
type
,
new_lens
,
find_permutation
(
inputs
));
}
const
auto
&
first_shape_lens
=
inputs
.
front
().
lens
();
const
auto
&
type
=
inputs
.
front
().
type
();
for
(
std
::
size_t
l
=
0
;
l
<
first_shape_lens
.
size
();
l
++
)
else
if
(
std
::
all_of
(
inputs
.
begin
(),
inputs
.
end
(),
[
&
](
const
shape
&
s
)
{
return
s
.
dynamic
();
}))
{
if
(
l
!=
axis
)
// Dynamic input shapes
for
(
std
::
size_t
index
=
0
;
index
<
inputs
[
0
].
ndim
();
index
++
)
{
if
(
not
std
::
all_of
(
inputs
.
begin
(),
inputs
.
end
(),
[
&
](
auto
s
)
{
return
s
.
lens
()[
l
]
==
first_shape_lens
[
l
];
}))
if
(
index
!=
axis
)
{
MIGRAPHX_THROW
(
"CONCAT: Non-axis dimensions should match"
);
if
(
not
std
::
all_of
(
inputs
.
begin
(),
inputs
.
end
(),
[
&
](
const
shape
&
s
)
{
return
s
.
dyn_dims
()[
index
]
==
inputs
[
0
].
dyn_dims
()[
index
];
}))
MIGRAPHX_THROW
(
"CONCAT: all input dimensions should match in axis "
+
std
::
to_string
(
index
));
}
}
std
::
size_t
new_min
=
0
;
std
::
size_t
new_max
=
0
;
for
(
const
auto
&
input
:
inputs
)
{
auto
ddim
=
input
.
dyn_dims
()[
axis
];
new_min
+=
ddim
.
min
;
new_max
+=
ddim
.
max
;
}
auto
new_dims
=
inputs
[
0
].
dyn_dims
();
new_dims
[
axis
]
=
migraphx
::
shape
::
dynamic_dimension
{
new_min
,
new_max
,
0
};
return
{
inputs
[
0
].
type
(),
new_dims
};
}
std
::
size_t
new_dim_axis
=
0
;
for
(
const
auto
&
input
:
inputs
)
else
{
const
auto
&
lens
=
input
.
lens
();
new_dim_axis
+=
lens
[
axis
];
MIGRAPHX_THROW
(
"CONCAT: Cannot mix static and dynamic input shapes."
);
}
std
::
vector
<
std
::
size_t
>
new_lens
;
std
::
copy
(
first_shape_lens
.
begin
(),
first_shape_lens
.
end
(),
std
::
back_inserter
(
new_lens
));
new_lens
[
axis
]
=
new_dim_axis
;
return
shape
::
from_permutation
(
type
,
new_lens
,
find_permutation
(
inputs
));
}
argument
compute
(
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
const
dyn_output
&
dyn_out
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
out
put_shape
};
std
::
vector
<
std
::
size_t
>
coffsets
=
compute_offsets
(
out
put_shape
,
args
);
argument
result
{
dyn_out
.
com
put
ed
_shape
};
std
::
vector
<
std
::
size_t
>
coffsets
=
compute_offsets
(
dyn_out
.
com
put
ed
_shape
,
args
);
for
(
std
::
size_t
l
=
0
;
l
<
args
.
size
();
l
++
)
{
auto
argl
=
args
[
l
];
visit_all
(
result
,
argl
)([
&
](
auto
output
,
auto
input
)
{
auto
slice_shape
=
shape
{
output_shape
.
type
(),
input
.
get_shape
().
lens
(),
output_shape
.
strides
()};
auto
slice
=
make_view
(
slice_shape
,
output
.
data
()
+
coffsets
[
l
]);
auto
slice_shape
=
shape
{
dyn_out
.
computed_shape
.
type
(),
input
.
get_shape
().
lens
(),
dyn_out
.
computed_shape
.
strides
()};
auto
slice
=
make_view
(
slice_shape
,
output
.
data
()
+
coffsets
[
l
]);
std
::
copy
(
input
.
begin
(),
input
.
end
(),
slice
.
begin
());
});
}
...
...
src/include/migraphx/op/gather.hpp
View file @
c9497134
...
...
@@ -26,6 +26,7 @@
#include <array>
#include <migraphx/check_shapes.hpp>
#include <migraphx/dyn_output.hpp>
#include <migraphx/stringutils.hpp>
#include <migraphx/streamutils.hpp>
#include <migraphx/literal.hpp>
...
...
@@ -61,35 +62,59 @@ struct gather
shape
normalize_compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
2
);
auto
lens
=
inputs
[
0
].
lens
();
auto
type
=
inputs
[
0
].
type
();
lens
.
erase
(
lens
.
begin
()
+
axis
);
if
(
not
inputs
[
1
].
scalar
())
check_shapes
{
inputs
,
*
this
,
true
}.
has
(
2
);
shape
data
=
inputs
[
0
];
shape
indices
=
inputs
[
1
];
auto
type
=
data
.
type
();
// If index_dims is dynamic, convert the data to dynamic too.
if
(
indices
.
dynamic
())
{
auto
ind_lens
=
inputs
[
1
].
lens
();
lens
.
insert
(
lens
.
begin
()
+
axis
,
ind_lens
.
begin
(),
ind_lens
.
end
());
data
=
data
.
to_dynamic
();
}
// for scalar output
if
(
lens
.
empty
())
if
(
data
.
dynamic
())
{
return
{
type
};
auto
dims
=
data
.
dyn_dims
();
dims
.
erase
(
dims
.
begin
()
+
axis
);
if
(
not
indices
.
scalar
())
{
auto
index_dims
=
indices
.
to_dynamic
().
dyn_dims
();
dims
.
insert
(
dims
.
begin
()
+
axis
,
index_dims
.
begin
(),
index_dims
.
end
());
}
return
{
type
,
dims
};
}
else
{
// Both data and indices are static. indices may be scalar
auto
lens
=
data
.
lens
();
lens
.
erase
(
lens
.
begin
()
+
axis
);
return
{
type
,
lens
};
if
(
not
indices
.
scalar
())
{
auto
ind_lens
=
indices
.
lens
();
lens
.
insert
(
lens
.
begin
()
+
axis
,
ind_lens
.
begin
(),
ind_lens
.
end
());
}
// for scalar output
if
(
lens
.
empty
())
{
return
{
type
};
}
return
{
type
,
lens
};
}
}
argument
compute
(
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
const
dyn_output
&
dyn_out
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
out
put_shape
};
argument
result
{
dyn_out
.
com
put
ed
_shape
};
// negative axis means counting dimensions from back
auto
lens
=
args
[
0
].
get_shape
().
lens
();
std
::
size_t
axis_dim_size
=
lens
[
axis
];
// max dimension in axis
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
data
)
{
args
[
1
].
visit
([
&
](
auto
indices
)
{
if
(
out
put_shape
.
scalar
())
if
(
dyn_out
.
com
put
ed
_shape
.
scalar
())
{
auto
in_index
=
indices
.
front
();
in_index
=
(
in_index
<
0
)
?
in_index
+
axis_dim_size
:
in_index
;
...
...
src/include/migraphx/op/gathernd.hpp
View file @
c9497134
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-202
2
Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2015-202
3
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
...
...
@@ -25,6 +25,7 @@
#define MIGRAPHX_GUARD_OPERATORS_GATHERND_HPP
#include <migraphx/check_shapes.hpp>
#include <migraphx/dyn_output.hpp>
#include <migraphx/shape_for_each.hpp>
#include <migraphx/par_for.hpp>
#include <migraphx/argument.hpp>
...
...
@@ -47,33 +48,103 @@ struct gathernd
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
2
);
auto
r
=
inputs
.
front
().
lens
().
size
();
auto
q
=
inputs
.
back
().
lens
().
size
();
auto
k
=
inputs
.
back
().
lens
().
back
();
check_shapes
{
inputs
,
*
this
,
true
}.
has
(
2
);
auto
i_shape
=
inputs
.
back
();
auto
data_shape
=
inputs
.
front
();
auto
r
=
data_shape
.
ndim
();
auto
q
=
i_shape
.
ndim
();
size_t
k
;
if
(
i_shape
.
dynamic
())
{
// the rank of the output is a function of k, so it must be fixed.
if
(
not
i_shape
.
dyn_dims
().
back
().
is_fixed
())
{
MIGRAPHX_THROW
(
"GATHERND: last dimension of indices tensor must be fixed (min=max)"
);
}
k
=
i_shape
.
dyn_dims
().
back
().
min
;
}
else
k
=
i_shape
.
lens
().
back
();
// Begin input validation checks.
int
output_ndim
=
int
(
q
)
+
r
-
k
-
batch_dims
-
1
;
if
(
k
>
r
-
batch_dims
)
{
MIGRAPHX_THROW
(
"GATHERND: Indices of length "
+
std
::
to_string
(
k
)
+
" cannot be used to access data of rank "
+
std
::
to_string
(
r
-
batch_dims
));
}
auto
indices_lens_iter
=
inputs
.
back
().
lens
().
begin
();
auto
output_lens_size
=
q
+
r
-
k
-
batch_dims
-
1
;
std
::
vector
<
std
::
size_t
>
output_lens
(
output_lens_size
);
std
::
copy
(
indices_lens_iter
,
indices_lens_iter
+
(
q
-
1
),
output_lens
.
begin
());
if
(
k
<
r
-
batch_dims
)
if
(
batch_dims
>=
q
or
batch_dims
>=
r
)
{
MIGRAPHX_THROW
(
"GATHERND: rank of an input cannot be less than batch_dims="
+
std
::
to_string
(
batch_dims
));
}
if
(
output_ndim
<
0
)
{
MIGRAPHX_THROW
(
"GATHERND: Indices too large for static data input: k="
+
std
::
to_string
(
k
));
}
if
(
migraphx
::
none_of
(
inputs
,
[](
auto
v
)
{
return
v
.
dynamic
();
}))
{
auto
indices_lens_iter
=
i_shape
.
lens
().
begin
();
// A rank 0 output is a scalar
if
(
output_ndim
==
0
)
return
shape
{
data_shape
.
type
(),
{
1
}};
// Part of the output shape comes from indices tensor, part from data tensor
std
::
vector
<
std
::
size_t
>
output_lens
(
output_ndim
);
std
::
copy
(
indices_lens_iter
,
indices_lens_iter
+
(
q
-
1
),
output_lens
.
begin
());
// fill the rest of output shape from data tensor
if
(
k
+
batch_dims
<
r
)
{
auto
data_lens
=
data_shape
.
lens
();
std
::
copy
(
data_lens
.
begin
()
+
batch_dims
+
k
,
data_lens
.
end
(),
output_lens
.
begin
()
+
q
-
1
);
}
shape
output_shape
{
data_shape
.
type
(),
output_lens
};
return
output_shape
;
}
else
{
auto
data_lens
=
inputs
.
front
().
lens
();
std
::
copy
(
data_lens
.
begin
()
+
batch_dims
+
k
,
data_lens
.
end
(),
output_lens
.
begin
()
+
q
-
1
);
// If one or both inputs are dynamic shapes, the output is dynamic.
// Make both inputs dynamic to simplify computations.
data_shape
=
data_shape
.
to_dynamic
();
i_shape
=
i_shape
.
to_dynamic
();
// A rank 0 output is a scalar
if
(
output_ndim
==
0
)
return
shape
(
data_shape
.
type
(),
{
shape
::
dynamic_dimension
({
1
,
1
,
0
})});
// Part of the output shape comes from indices tensor, part from data tensor
std
::
vector
<
shape
::
dynamic_dimension
>
output_dims
(
output_ndim
);
std
::
copy
(
i_shape
.
dyn_dims
().
begin
(),
i_shape
.
dyn_dims
().
begin
()
+
q
-
1
,
output_dims
.
begin
());
// fill the rest of output shape from data tensor
if
(
k
+
batch_dims
<
r
)
{
auto
data_dims
=
data_shape
.
dyn_dims
();
std
::
copy
(
data_dims
.
begin
()
+
batch_dims
+
k
,
data_dims
.
begin
()
+
r
,
output_dims
.
begin
()
+
q
-
1
);
}
shape
output_shape
(
data_shape
.
type
(),
output_dims
);
return
output_shape
;
}
shape
output_shape
{
inputs
.
front
().
type
(),
output_lens
};
return
output_shape
;
}
argument
compute
(
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
const
dyn_output
&
dyn_out
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
out
put_shape
};
argument
result
{
dyn_out
.
com
put
ed
_shape
};
visit_all
(
result
,
args
[
0
])([
&
](
auto
output
,
auto
data
)
{
args
[
1
].
visit
([
&
](
auto
indices
)
{
auto
indices_shape
=
indices
.
get_shape
();
...
...
src/include/migraphx/op/normalize_attribute.hpp
View file @
c9497134
...
...
@@ -31,18 +31,30 @@ namespace migraphx {
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
op
{
// different attributes
// 1) use_input(default)/use_output
// 2) use_rank(default)/use_len
// 3) clip_min(default)/not_clip_min
// 3.1) include_min(default)/exclude_min
// 4) clip_max(default)/not_clip_max
// 4.1) exclude_max(default)/include_max
// 5) normalize padding
/**
* `normalize_attribute` settings:
* Note that default options are not included as enums.
* 1. `use_input` (default) vs. `use_output`:
* Affects the rank of the attribute.
* `use_input -> lens.size()`, `use_output -> lens.size() + vec.size()`.
* 2. use_rank (default) vs use_len:
* `use_rank` sets the max value/index of the attribute as the rank of lens.
* `use_lens` sets the max value/index as the corresponding value in lens at the axes index.
* 3. `clip_min` vs. `not_clip_min` (default):
* Clip values less than the minimum to the minimum or not.
* 4. `include_min` vs. `exclude_min` (default):
* Include or exclude the minimum value/index for range checking and clipping.
* 5. `clip_max` vs. `not_clip_max` (default):
* Clip values greater than the maximum or not.
* 6. `include_max` vs. `exclude_max` (default):
* Include or exclude the maximum value/index for range checking and clipping.
* 7. `normalize_padding`:
* To normalize the padding to `2*(pad ndim)` dimensions.
*/
enum
class
normalize_attribute
{
use_len
,
use_output
,
use_len
,
clip_max
,
clip_min
,
include_max
,
...
...
src/include/migraphx/op/scatternd_op.hpp
View file @
c9497134
...
...
@@ -28,44 +28,89 @@
#include <migraphx/check_shapes.hpp>
#include <migraphx/argument.hpp>
#include <migraphx/par_for.hpp>
#include <migraphx/ranges.hpp>
namespace
migraphx
{
inline
namespace
MIGRAPHX_INLINE_NS
{
namespace
op
{
/**
* @brief
* N-dimensional Scatter operations. This struct is parent class to ops which differ in what formula
* is used to reduce (combine old and new values of) the scattered value. It was originally based
* on Onnx ScatterND operation (see
* https://github.com/onnx/onnx/blob/main/docs/Operators.md#ScatterND) and is also similar to Numpy
* numpy.add.at().
*
* @tparam Derived a template parameter in the CRTP inheritance idiom, represents one of the child
* operations.
*/
template
<
class
Derived
>
struct
scatternd_op
:
op_name
<
Derived
>
{
/** Validate input shapes and return the correct output shape. For Scatter ops, the output
* is the same shape as the data tensor (first input), but cast to a standard shape.
*
*/
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
3
);
auto
r
=
inputs
.
front
().
lens
().
size
();
auto
q
=
inputs
.
at
(
1
).
lens
().
size
();
auto
k
=
inputs
.
at
(
1
).
lens
().
back
();
auto
ind_lens
=
inputs
.
at
(
1
).
lens
();
auto
upd_lens
=
inputs
.
back
().
lens
();
auto
data_lens
=
inputs
.
front
().
lens
();
check_shapes
{
inputs
,
*
this
,
true
}.
has
(
3
);
auto
data_shape
=
inputs
.
front
();
auto
index_shape
=
inputs
.
at
(
1
);
auto
upd_shape
=
inputs
.
back
();
auto
r
=
data_shape
.
ndim
();
auto
q
=
index_shape
.
ndim
();
size_t
k
;
if
(
index_shape
.
dynamic
())
{
// the rank of the output is a function of k, so k must be fixed.
if
(
not
index_shape
.
dyn_dims
().
back
().
is_fixed
())
{
MIGRAPHX_THROW
(
"GATHERND: last dimension of indices tensor must be fixed (min=max)"
);
}
k
=
index_shape
.
dyn_dims
().
back
().
min
;
}
else
k
=
index_shape
.
lens
().
back
();
// Checks on the sizes of input tensors
if
(
q
+
r
!=
upd_shape
.
ndim
()
+
k
+
1
)
MIGRAPHX_THROW
(
"ScatterND: ranks of inputs don't match. "
+
std
::
to_string
(
q
)
+
" + "
+
std
::
to_string
(
r
)
+
" - "
+
std
::
to_string
(
k
)
+
" - 1 != "
+
std
::
to_string
(
upd_shape
.
ndim
()));
if
(
k
>
r
)
MIGRAPHX_THROW
(
"ScatterND: index of size "
+
std
::
to_string
(
k
)
+
" is too large for tensor of rank "
+
std
::
to_string
(
r
));
if
(
not
(
std
::
equal
(
ind_lens
.
begin
(),
ind_lens
.
begin
()
+
q
-
1
,
upd_lens
.
begin
())
and
std
::
equal
(
data_lens
.
begin
()
+
k
,
data_lens
.
end
(),
upd_lens
.
begin
()
+
q
-
1
)))
MIGRAPHX_THROW
(
"ScatterND: incorrect update shape. update.lens != indices.lens[0:q-1] "
"++ data.lens[k:r-1]"
);
auto
s
=
inputs
.
front
();
if
(
s
.
broadcasted
())
// Convert all static shape dimensions to dynamic so they can be compared.
// It's possible for some of the 3 inputs to be dynamic shapes and some static,
// but any dynamic dimension that's compared to a static dimension must be fixed.
auto
ind_dims
=
index_shape
.
to_dynamic
().
dyn_dims
();
auto
upd_dims
=
upd_shape
.
to_dynamic
().
dyn_dims
();
auto
data_dims
=
data_shape
.
to_dynamic
().
dyn_dims
();
// Check that corresponding portions of tensor shapes match.
if
(
not
(
std
::
equal
(
ind_dims
.
begin
(),
ind_dims
.
begin
()
+
q
-
1
,
upd_dims
.
begin
())
and
std
::
equal
(
data_dims
.
begin
()
+
k
,
data_dims
.
end
(),
upd_dims
.
begin
()
+
q
-
1
)))
MIGRAPHX_THROW
(
"ScatterND: incorrect update shape. Update dimensions must match "
"indices and data."
);
if
(
data_shape
.
dynamic
())
return
data_shape
;
else
if
(
data_shape
.
broadcasted
())
{
return
{
s
.
type
(),
s
.
lens
()};
return
{
data_shape
.
type
(),
data_shape
.
lens
()};
}
else
{
return
s
.
with_lens
(
s
.
lens
());
return
data_shape
.
with_lens
(
data_shape
.
lens
());
}
}
argument
compute
(
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
const
dyn_output
&
dyn_out
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
out
put_shape
};
argument
result
{
dyn_out
.
com
put
ed
_shape
};
auto
&
self
=
static_cast
<
const
Derived
&>
(
*
this
);
visit_all
(
result
,
args
[
0
],
args
[
2
])([
&
](
auto
output
,
auto
data
,
auto
updates
)
{
std
::
copy
(
data
.
begin
(),
data
.
end
(),
output
.
begin
());
...
...
@@ -74,8 +119,8 @@ struct scatternd_op : op_name<Derived>
auto
updates_std
=
shape
{
updates_shape
.
type
(),
updates_shape
.
lens
()};
auto
indices_shape
=
indices
.
get_shape
();
auto
k
=
indices_shape
.
lens
().
back
();
auto
q
=
indices_shape
.
lens
().
size
();
auto
r
=
out
put_shape
.
lens
().
size
();
auto
q
=
indices_shape
.
ndim
();
auto
r
=
dyn_out
.
com
put
ed
_shape
.
ndim
();
par_for
(
updates_shape
.
elements
(),
[
&
](
const
auto
i
)
{
auto
updates_idx
=
updates_std
.
multi
(
i
);
std
::
vector
<
std
::
size_t
>
indices_idx
(
q
,
0
);
...
...
@@ -89,7 +134,7 @@ struct scatternd_op : op_name<Derived>
std
::
copy
(
index_start
,
index_end
,
out_idx
.
begin
());
std
::
copy
(
updates_idx
.
begin
()
+
q
-
1
,
updates_idx
.
end
(),
out_idx
.
begin
()
+
k
);
self
.
reduction
()(
output
[
out
put_shape
.
index
(
out_idx
)],
updates
[
i
]);
self
.
reduction
()(
output
[
dyn_out
.
com
put
ed
_shape
.
index
(
out_idx
)],
updates
[
i
]);
});
});
});
...
...
src/include/migraphx/op/where.hpp
View file @
c9497134
/*
* The MIT License (MIT)
*
* Copyright (c) 2015-202
2
Advanced Micro Devices, Inc. All rights reserved.
* Copyright (c) 2015-202
3
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
...
...
@@ -42,9 +42,17 @@ struct where
shape
compute_shape
(
std
::
vector
<
shape
>
inputs
)
const
{
check_shapes
{
inputs
,
*
this
}.
has
(
3
).
same_dims
();
check_shapes
{
inputs
,
*
this
,
true
}.
has
(
3
).
same_dims
();
auto
s1
=
inputs
.
at
(
1
);
auto
s2
=
inputs
.
at
(
2
);
if
(
s1
.
dynamic
()
or
s2
.
dynamic
())
{
if
(
s1
==
s2
)
return
s1
;
MIGRAPHX_THROW
(
"WHERE: dynamic input shapes must be the same"
);
}
// Compare two static shapes, returning a standard shape
if
(
s1
==
s2
and
s1
.
packed
())
{
return
s1
;
...
...
@@ -63,12 +71,12 @@ struct where
}
}
argument
compute
(
const
shape
&
output_shape
,
std
::
vector
<
argument
>
args
)
const
argument
compute
(
const
dyn_output
&
dyn_out
,
std
::
vector
<
argument
>
args
)
const
{
argument
result
{
out
put_shape
};
argument
result
{
dyn_out
.
com
put
ed
_shape
};
visit_all
(
result
,
args
[
1
],
args
[
2
])([
&
](
auto
output
,
const
auto
x
,
const
auto
y
)
{
args
[
0
].
visit
([
&
](
const
auto
condition
)
{
par_for
(
out
put_shape
.
elements
(),
par_for
(
dyn_out
.
com
put
ed
_shape
.
elements
(),
[
&
](
auto
i
)
{
output
[
i
]
=
condition
[
i
]
?
x
[
i
]
:
y
[
i
];
});
});
});
...
...
Prev
1
2
3
4
5
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment