Toggle navigation
Toggle navigation
此项目
正在载入...
Sign in
xuning
/
sherpaonnx
转到一个项目
Toggle navigation
项目
群组
代码片段
帮助
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
Fangjun Kuang
2023-03-08 14:12:20 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Committed by
GitHub
2023-03-08 14:12:20 +0800
Commit
8c6a289e3d1a2d3020fea58cc00dbaa2148e6e36
8c6a289e
1 parent
3a791158
Add PackPaddedSequence (#85)
显示空白字符变更
内嵌
并排对比
正在显示
7 个修改的文件
包含
235 行增加
和
20 行删除
sherpa-onnx/csrc/CMakeLists.txt
sherpa-onnx/csrc/packed-sequence-test.cc
sherpa-onnx/csrc/packed-sequence.cc
sherpa-onnx/csrc/packed-sequence.h
sherpa-onnx/csrc/slice-test.cc
sherpa-onnx/csrc/slice.cc
sherpa-onnx/csrc/slice.h
sherpa-onnx/csrc/CMakeLists.txt
查看文件 @
8c6a289
...
...
@@ -16,6 +16,7 @@ set(sources
online-transducer-modified-beam-search-decoder.cc
online-zipformer-transducer-model.cc
onnx-utils.cc
packed-sequence.cc
pad-sequence.cc
parse-options.cc
resample.cc
...
...
@@ -123,6 +124,7 @@ endif()
if
(
SHERPA_ONNX_ENABLE_TESTS
)
set
(
sherpa_onnx_test_srcs
cat-test.cc
packed-sequence-test.cc
pad-sequence-test.cc
slice-test.cc
transpose-test.cc
...
...
sherpa-onnx/csrc/packed-sequence-test.cc
0 → 100644
查看文件 @
8c6a289
// sherpa-onnx/csrc/packed-sequence-test.cc
//
// Copyright (c) 2023 Xiaomi Corporation
#include "sherpa-onnx/csrc/packed-sequence.h"
#include <numeric>
#include "gtest/gtest.h"
#include "sherpa-onnx/csrc/onnx-utils.h"
namespace
sherpa_onnx
{
TEST
(
PackedSequence
,
Case1
)
{
Ort
::
AllocatorWithDefaultOptions
allocator
;
std
::
array
<
int64_t
,
3
>
shape
{
5
,
5
,
4
};
Ort
::
Value
v
=
Ort
::
Value
::
CreateTensor
<
float
>
(
allocator
,
shape
.
data
(),
shape
.
size
());
float
*
p
=
v
.
GetTensorMutableData
<
float
>
();
std
::
iota
(
p
,
p
+
shape
[
0
]
*
shape
[
1
]
*
shape
[
2
],
0
);
Ort
::
Value
length
=
Ort
::
Value
::
CreateTensor
<
int64_t
>
(
allocator
,
shape
.
data
(),
1
);
int64_t
*
p_length
=
length
.
GetTensorMutableData
<
int64_t
>
();
p_length
[
0
]
=
1
;
p_length
[
1
]
=
2
;
p_length
[
2
]
=
3
;
p_length
[
3
]
=
5
;
p_length
[
4
]
=
2
;
auto
packed_seq
=
PackPaddedSequence
(
allocator
,
&
v
,
&
length
);
fprintf
(
stderr
,
"sorted indexes: "
);
for
(
auto
i
:
packed_seq
.
sorted_indexes
)
{
fprintf
(
stderr
,
"%d "
,
static_cast
<
int32_t
>
(
i
));
}
fprintf
(
stderr
,
"
\n
"
);
// output index: 0 1 2 3 4
// sorted indexes: 3 2 1 4 0
// length: 5 3 2 2 1
Print3D
(
&
v
);
Print2D
(
&
packed_seq
.
data
);
fprintf
(
stderr
,
"batch sizes per time step: "
);
for
(
auto
i
:
packed_seq
.
batch_sizes
)
{
fprintf
(
stderr
,
"%d "
,
static_cast
<
int32_t
>
(
i
));
}
fprintf
(
stderr
,
"
\n
"
);
// TODO(fangjun): Check that the return value is correct
}
}
// namespace sherpa_onnx
...
...
sherpa-onnx/csrc/packed-sequence.cc
0 → 100644
查看文件 @
8c6a289
// sherpa-onnx/csrc/packed-sequence.cc
//
// Copyright (c) 2023 Xiaomi Corporation
#include "sherpa-onnx/csrc/packed-sequence.h"
#include <assert.h>
#include <algorithm>
#include <numeric>
#include <utility>
#include "sherpa-onnx/csrc/slice.h"
#include "sherpa-onnx/csrc/transpose.h"
namespace
sherpa_onnx
{
static
Ort
::
Value
IndexSelect
(
OrtAllocator
*
allocator
,
const
Ort
::
Value
*
value
,
const
std
::
vector
<
int32_t
>
&
sorted_indexes
)
{
auto
shape
=
value
->
GetTensorTypeAndShapeInfo
().
GetShape
();
assert
(
shape
.
size
()
==
3
);
std
::
array
<
int64_t
,
3
>
ans_shape
{
static_cast
<
int64_t
>
(
sorted_indexes
.
size
()),
shape
[
1
],
shape
[
2
]};
Ort
::
Value
ans
=
Ort
::
Value
::
CreateTensor
<
float
>
(
allocator
,
ans_shape
.
data
(),
ans_shape
.
size
());
float
*
dst
=
ans
.
GetTensorMutableData
<
float
>
();
const
float
*
src
=
value
->
GetTensorData
<
float
>
();
for
(
auto
i
:
sorted_indexes
)
{
const
float
*
start
=
src
+
i
*
shape
[
1
]
*
shape
[
2
];
std
::
copy
(
start
,
start
+
shape
[
1
]
*
shape
[
2
],
dst
);
dst
+=
shape
[
1
]
*
shape
[
2
];
}
return
ans
;
}
PackedSequence
PackPaddedSequence
(
OrtAllocator
*
allocator
,
const
Ort
::
Value
*
value
,
Ort
::
Value
*
length
)
{
std
::
vector
<
int64_t
>
v_shape
=
value
->
GetTensorTypeAndShapeInfo
().
GetShape
();
std
::
vector
<
int64_t
>
l_shape
=
length
->
GetTensorTypeAndShapeInfo
().
GetShape
();
assert
(
v_shape
.
size
()
==
3
);
assert
(
l_shape
.
size
()
==
3
);
assert
(
v_shape
[
0
]
==
l_shape
[
0
]);
std
::
vector
<
int32_t
>
indexes
(
v_shape
[
0
]);
std
::
iota
(
indexes
.
begin
(),
indexes
.
end
(),
0
);
const
int64_t
*
p_length
=
length
->
GetTensorData
<
int64_t
>
();
// sort in descending order
std
::
sort
(
indexes
.
begin
(),
indexes
.
end
(),
[
p_length
](
int32_t
i
,
int32_t
j
)
{
return
p_length
[
i
]
>
p_length
[
j
];
});
int32_t
n
=
static_cast
<
int32_t
>
(
v_shape
[
0
]);
int64_t
max_T
=
p_length
[
indexes
[
0
]];
int32_t
sum_T
=
std
::
accumulate
(
p_length
,
p_length
+
n
,
0
);
std
::
array
<
int64_t
,
2
>
data_shape
{
sum_T
,
v_shape
[
2
]};
Ort
::
Value
data
=
Ort
::
Value
::
CreateTensor
<
float
>
(
allocator
,
data_shape
.
data
(),
data_shape
.
size
());
float
*
dst
=
data
.
GetTensorMutableData
<
float
>
();
Ort
::
Value
tensor
=
IndexSelect
(
allocator
,
value
,
indexes
);
tensor
=
Transpose01
(
allocator
,
&
tensor
);
// batch size at each time step
std
::
vector
<
int32_t
>
batch_sizes
;
batch_sizes
.
reserve
(
max_T
);
int64_t
prev_l
=
0
;
for
(
int32_t
i
=
0
;
i
!=
n
;
++
i
)
{
auto
cur_l
=
p_length
[
indexes
[
n
-
1
-
i
]];
assert
(
cur_l
>=
prev_l
);
if
(
cur_l
==
prev_l
)
{
continue
;
}
auto
cur_batch_size
=
n
-
i
;
Ort
::
Value
cur_batch
=
Slice
(
allocator
,
&
tensor
,
prev_l
,
cur_l
,
0
,
cur_batch_size
);
auto
count
=
cur_batch
.
GetTensorTypeAndShapeInfo
().
GetElementCount
();
const
float
*
src
=
cur_batch
.
GetTensorData
<
float
>
();
std
::
copy
(
src
,
src
+
count
,
dst
);
dst
+=
count
;
for
(
int32_t
j
=
prev_l
;
j
<
cur_l
;
++
j
)
{
batch_sizes
.
push_back
(
cur_batch_size
);
}
prev_l
=
cur_l
;
}
PackedSequence
packed_seq
;
packed_seq
.
sorted_indexes
=
std
::
move
(
indexes
);
packed_seq
.
data
=
std
::
move
(
data
);
packed_seq
.
batch_sizes
=
std
::
move
(
batch_sizes
);
return
packed_seq
;
}
}
// namespace sherpa_onnx
...
...
sherpa-onnx/csrc/packed-sequence.h
0 → 100644
查看文件 @
8c6a289
// sherpa-onnx/csrc/packed-sequence.h
//
// Copyright (c) 2023 Xiaomi Corporation
#ifndef SHERPA_ONNX_CSRC_PACKED_SEQUENCE_H_
#define SHERPA_ONNX_CSRC_PACKED_SEQUENCE_H_
#include <vector>
#include "onnxruntime_cxx_api.h" // NOLINT
namespace
sherpa_onnx
{
struct
PackedSequence
{
std
::
vector
<
int32_t
>
sorted_indexes
;
std
::
vector
<
int32_t
>
batch_sizes
;
Ort
::
Value
data
{
nullptr
};
};
/** Similar to torch.nn.utils.rnn.pad_sequence but it supports only
* batch_first=true.
*
* @param allocator
* @param value A 3-D tensor of shape (B, T, C). Its dtype is float.
* @param length A 1-D tensor of shape (B,). Its dtype is int64_t. Each
* element in it specifies the valid length of the corresponding
* entry in value before padding.
*/
PackedSequence
PackPaddedSequence
(
OrtAllocator
*
allocator
,
const
Ort
::
Value
*
value
,
Ort
::
Value
*
length
);
}
// namespace sherpa_onnx
#endif // SHERPA_ONNX_CSRC_PACKED_SEQUENCE_H_
...
...
sherpa-onnx/csrc/slice-test.cc
查看文件 @
8c6a289
...
...
@@ -13,19 +13,19 @@ namespace sherpa_onnx {
TEST
(
Slice
,
Slice3D
)
{
Ort
::
AllocatorWithDefaultOptions
allocator
;
std
::
array
<
int64_t
,
3
>
shape
{
3
,
5
,
4
};
std
::
array
<
int64_t
,
3
>
shape
{
5
,
5
,
4
};
Ort
::
Value
v
=
Ort
::
Value
::
CreateTensor
<
float
>
(
allocator
,
shape
.
data
(),
shape
.
size
());
float
*
p
=
v
.
GetTensorMutableData
<
float
>
();
std
::
iota
(
p
,
p
+
shape
[
0
]
*
shape
[
1
]
*
shape
[
2
],
0
);
auto
v1
=
Slice
(
&
v
,
0
,
2
,
5
);
auto
v2
=
Slice
(
&
v
,
1
,
2
,
4
);
auto
v1
=
Slice
(
allocator
,
&
v
,
2
,
4
,
0
,
2
);
auto
v2
=
Slice
(
allocator
,
&
v
,
1
,
3
,
1
,
3
);
Print3D
(
&
v
);
Print2D
(
&
v1
);
Print2D
(
&
v2
);
Print3D
(
&
v1
);
Print3D
(
&
v2
);
// TODO(fangjun): Check that the results are correct
}
...
...
sherpa-onnx/csrc/slice.cc
查看文件 @
8c6a289
...
...
@@ -6,29 +6,48 @@
#include <assert.h>
#include <algorithm>
#include <vector>
namespace
sherpa_onnx
{
template
<
typename
T
/*=float*/
>
Ort
::
Value
Slice
(
const
Ort
::
Value
*
v
,
int32_t
dim0
,
int32_t
dim1_start
,
Ort
::
Value
Slice
(
OrtAllocator
*
allocator
,
const
Ort
::
Value
*
v
,
int32_t
dim0_start
,
int32_t
dim0_end
,
int32_t
dim1_start
,
int32_t
dim1_end
)
{
std
::
vector
<
int64_t
>
shape
=
v
->
GetTensorTypeAndShapeInfo
().
GetShape
();
assert
(
shape
.
size
()
==
3
);
auto
memory_info
=
Ort
::
MemoryInfo
::
CreateCpu
(
OrtDeviceAllocator
,
OrtMemTypeDefault
);
assert
(
0
<=
dim0_start
);
assert
(
dim0_start
<
dim0_end
);
assert
(
dim0_end
<=
shape
[
0
]);
assert
(
0
<=
dim1_start
);
assert
(
dim1_start
<
dim1_end
);
assert
(
dim1_end
<
shape
[
1
]);
std
::
array
<
int64_t
,
2
>
ans_shape
{
dim1_end
-
dim1_start
,
shape
[
2
]};
const
T
*
src
=
v
->
GetTensorData
<
T
>
();
src
+=
dim0
*
shape
[
1
]
*
shape
[
2
]
+
dim1_start
*
shape
[
2
];
return
Ort
::
Value
::
CreateTensor
(
memory_info
,
const_cast
<
T
*>
(
src
),
ans_shape
[
0
]
*
ans_shape
[
1
],
ans_shape
.
data
(),
std
::
array
<
int64_t
,
3
>
ans_shape
{
dim0_end
-
dim0_start
,
dim1_end
-
dim1_start
,
shape
[
2
]};
Ort
::
Value
ans
=
Ort
::
Value
::
CreateTensor
<
T
>
(
allocator
,
ans_shape
.
data
(),
ans_shape
.
size
());
T
*
dst
=
ans
.
GetTensorMutableData
<
T
>
();
for
(
int32_t
i
=
dim0_start
;
i
!=
dim0_end
;
++
i
)
{
const
T
*
src
=
v
->
GetTensorData
<
T
>
()
+
i
*
shape
[
1
]
*
shape
[
2
];
const
T
*
start
=
src
+
dim1_start
*
shape
[
2
];
const
T
*
end
=
src
+
dim1_end
*
shape
[
2
];
std
::
copy
(
start
,
end
,
dst
);
dst
+=
ans_shape
[
1
]
*
ans_shape
[
2
];
}
return
ans
;
}
template
Ort
::
Value
Slice
<
float
>
(
const
Ort
::
Value
*
v
,
int32_t
dim0
,
template
Ort
::
Value
Slice
<
float
>
(
OrtAllocator
*
allocator
,
const
Ort
::
Value
*
v
,
int32_t
dim0_start
,
int32_t
dim0_end
,
int32_t
dim1_start
,
int32_t
dim1_end
);
}
// namespace sherpa_onnx
...
...
sherpa-onnx/csrc/slice.h
查看文件 @
8c6a289
...
...
@@ -8,21 +8,23 @@
namespace
sherpa_onnx
{
/** Get a
shallow
copy by slicing v.
/** Get a
deep
copy by slicing v.
*
* It returns v[dim0, dim1_start:dim1_end]
* It returns v[dim0
_start:dim0_end
, dim1_start:dim1_end]
*
* @param allocator
* @param v A 3-D tensor. Its data type is T.
* @param dim0 Start index of the first dimension..
* @param dim0_start Start index of the first dimension..
* @param dim0_end End index of the first dimension..
* @param dim1_start Start index of the second dimension.
* @param dim1_end End index of the second dimension.
*
* @return Return a 2-D tensor of shape (dim1_end-dim1_start, v.shape[2])
*
* @caution: The returned tensor is a shallow copy of `v`!
* @return Return a 3-D tensor of shape
* (dim0_end-dim0_start, dim1_end-dim1_start, v.shape[2])
*/
template
<
typename
T
=
float
>
Ort
::
Value
Slice
(
const
Ort
::
Value
*
v
,
int32_t
dim0
,
int32_t
dim1_start
,
Ort
::
Value
Slice
(
OrtAllocator
*
allocator
,
const
Ort
::
Value
*
v
,
int32_t
dim0_start
,
int32_t
dim0_end
,
int32_t
dim1_start
,
int32_t
dim1_end
);
}
// namespace sherpa_onnx
...
...
请
注册
或
登录
后发表评论