Допустим, у меня есть 3d-массив как сплющенный 1d с размерами [N, M, K]
. И я хочу обработать кусок из него как [0:N, 1:M, 0:K]
.
Я создал вспомогательную функцию, которая обращается к базовому массиву по индексам из нарезанного массива (для простоты я делаю срезы только по второму измерению).
#define N somevalue
#define M somevalue
#define K somevalue
// i is an index in sliced array so we need to translate it into original one
template<class T, int FROM>
__device__ __forceinline__ T slice(const T * const __restrict__ x, const size_t i) {
auto batch_size = (M - FROM) * K;
auto batch_index = i / batch_size;
auto offset_0 = i % batch_size;
auto offset_1 = offset_0 / STATES;
auto offset_2 = offset_0 % STATES;
return x[batch_index * M * K + (offset_1 + FROM) * K + offset_2];
}
От профилировщика NVidia я вижу, что деление и деление по модулю отнимают много вычислительных ресурсов. Также размеры не являются степенью 2, поэтому я не могу использовать трюк с битами сдвига напрямую.
Что вы можете посоветовать?
Как я знаю, нарезка является довольно распространенной операцией в TF, так как они решили ее?