Skip to content

Commit

Permalink
AVX2-optimization of search functions for maximum and minimum
Browse files Browse the repository at this point in the history
  • Loading branch information
sadko4u committed Oct 19, 2023
1 parent f7607fd commit 7e6c96c
Show file tree
Hide file tree
Showing 17 changed files with 1,380 additions and 401 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*******************************************************************************

=== 1.0.19 ===

* AVX2-optimization of search functions for maximum and minimum.

=== 1.0.18 ===
* Fixed compilation regression for 32-bit Clang compiler.
Expand Down
4 changes: 2 additions & 2 deletions include/private/dsp/arch/x86/avx2/search/iminmax.h
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ namespace lsp
#undef IMINMAX2_CORE
#undef SEL_NONE
#undef SEL_ABS
}
}
} /* namespace avx2 */
} /* namespace lsp */

#endif /* PRIVATE_DSP_ARCH_X86_AVX2_SEARCH_IMINMAX_H_ */
8 changes: 8 additions & 0 deletions src/main/x86/avx2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ namespace lsp
CEXPORT2_X64(favx, exp1, x64_exp1);
CEXPORT2_X64(favx, exp2, x64_exp2);

EXPORT1(min_index);
EXPORT1(max_index);
EXPORT1(minmax_index);

EXPORT1(abs_min_index);
EXPORT1(abs_max_index);
EXPORT1(abs_minmax_index);

CEXPORT1(favx, logb1);
CEXPORT1(favx, logb2);
CEXPORT1(favx, loge1);
Expand Down
114 changes: 114 additions & 0 deletions src/test/ptest/search/abs_max_index.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2023 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2023 Vladimir Sadovnikov <[email protected]>
*
* This file is part of lsp-dsp-lib
* Created on: 31 мар. 2020 г.
*
* lsp-dsp-lib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-dsp-lib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-dsp-lib. If not, see <https://www.gnu.org/licenses/>.
*/

#include <lsp-plug.in/common/alloc.h>
#include <lsp-plug.in/common/types.h>
#include <lsp-plug.in/test-fw/helpers.h>
#include <lsp-plug.in/test-fw/ptest.h>

#define MIN_RANK 8
#define MAX_RANK 16

namespace lsp
{
namespace generic
{
size_t abs_max_index(const float *src, size_t count);
}

IF_ARCH_X86(
namespace sse2
{
size_t abs_max_index(const float *src, size_t count);
}

namespace avx2
{
size_t abs_max_index(const float *src, size_t count);
}
)

IF_ARCH_ARM(
namespace neon_d32
{
size_t abs_max_index(const float *src, size_t count);
}
)

IF_ARCH_AARCH64(
namespace asimd
{
size_t abs_max_index(const float *src, size_t count);
}
)

typedef size_t (* cond_index_t)(const float *src, size_t count);
}

//-----------------------------------------------------------------------------
// Performance test for minimum and maximum searching
PTEST_BEGIN("dsp.search", abs_max_index, 5, 1000)

void call(const char *label, const float *in, size_t count, cond_index_t func)
{
if (!PTEST_SUPPORTED(func))
return;

char buf[80];
sprintf(buf, "%s x %d", label, int(count));
printf("Testing %s numbers...\n", buf);

PTEST_LOOP(buf,
func(in, count);
);
}

PTEST_MAIN
{
size_t buf_size = 1 << MAX_RANK;
uint8_t *data = NULL;

float *in = alloc_aligned<float>(data, buf_size, 64);
for (size_t i=0; i < (1 << MAX_RANK); ++i)
in[i] = randf(-1.0f, 1.0f);

#define CALL(func) \
call(#func, in, count, func)

for (size_t i=MIN_RANK; i <= MAX_RANK; ++i)
{
size_t count = 1 << i;

//--------------
CALL(generic::abs_max_index);
IF_ARCH_X86(CALL(sse2::abs_max_index));
IF_ARCH_X86(CALL(avx2::abs_max_index));
IF_ARCH_ARM(CALL(neon_d32::abs_max_index));
IF_ARCH_AARCH64(CALL(asimd::abs_max_index));
PTEST_SEPARATOR;
}

free_aligned(data);
}

PTEST_END


114 changes: 114 additions & 0 deletions src/test/ptest/search/abs_min_index.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2023 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2023 Vladimir Sadovnikov <[email protected]>
*
* This file is part of lsp-dsp-lib
* Created on: 31 мар. 2020 г.
*
* lsp-dsp-lib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-dsp-lib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-dsp-lib. If not, see <https://www.gnu.org/licenses/>.
*/

#include <lsp-plug.in/common/alloc.h>
#include <lsp-plug.in/common/types.h>
#include <lsp-plug.in/test-fw/helpers.h>
#include <lsp-plug.in/test-fw/ptest.h>

#define MIN_RANK 8
#define MAX_RANK 16

namespace lsp
{
namespace generic
{
size_t abs_min_index(const float *src, size_t count);
}

IF_ARCH_X86(
namespace sse2
{
size_t abs_min_index(const float *src, size_t count);
}

namespace avx2
{
size_t abs_min_index(const float *src, size_t count);
}
)

IF_ARCH_ARM(
namespace neon_d32
{
size_t abs_min_index(const float *src, size_t count);
}
)

IF_ARCH_AARCH64(
namespace asimd
{
size_t abs_min_index(const float *src, size_t count);
}
)

typedef size_t (* cond_index_t)(const float *src, size_t count);
}

//-----------------------------------------------------------------------------
// Performance test for minimum and maximum searching
PTEST_BEGIN("dsp.search", abs_min_index, 5, 1000)

void call(const char *label, const float *in, size_t count, cond_index_t func)
{
if (!PTEST_SUPPORTED(func))
return;

char buf[80];
sprintf(buf, "%s x %d", label, int(count));
printf("Testing %s numbers...\n", buf);

PTEST_LOOP(buf,
func(in, count);
);
}

PTEST_MAIN
{
size_t buf_size = 1 << MAX_RANK;
uint8_t *data = NULL;

float *in = alloc_aligned<float>(data, buf_size, 64);
for (size_t i=0; i < (1 << MAX_RANK); ++i)
in[i] = randf(-1.0f, 1.0f);

#define CALL(func) \
call(#func, in, count, func)

for (size_t i=MIN_RANK; i <= MAX_RANK; ++i)
{
size_t count = 1 << i;

//--------------
CALL(generic::abs_min_index);
IF_ARCH_X86(CALL(sse2::abs_min_index));
IF_ARCH_X86(CALL(avx2::abs_min_index));
IF_ARCH_ARM(CALL(neon_d32::abs_min_index));
IF_ARCH_AARCH64(CALL(asimd::abs_min_index));
PTEST_SEPARATOR;
}

free_aligned(data);
}

PTEST_END


114 changes: 114 additions & 0 deletions src/test/ptest/search/abs_minmax_index.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* Copyright (C) 2023 Linux Studio Plugins Project <https://lsp-plug.in/>
* (C) 2023 Vladimir Sadovnikov <[email protected]>
*
* This file is part of lsp-dsp-lib
* Created on: 31 мар. 2020 г.
*
* lsp-dsp-lib is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* lsp-dsp-lib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with lsp-dsp-lib. If not, see <https://www.gnu.org/licenses/>.
*/

#include <lsp-plug.in/common/alloc.h>
#include <lsp-plug.in/common/types.h>
#include <lsp-plug.in/test-fw/helpers.h>
#include <lsp-plug.in/test-fw/ptest.h>

#define MIN_RANK 8
#define MAX_RANK 16

namespace lsp
{
namespace generic
{
void abs_minmax_index(const float *src, size_t count, size_t *min, size_t *max);
}

IF_ARCH_X86(
namespace sse2
{
void abs_minmax_index(const float *src, size_t count, size_t *min, size_t *max);
}

namespace avx2
{
void abs_minmax_index(const float *src, size_t count, size_t *min, size_t *max);
}
)

IF_ARCH_ARM(
namespace neon_d32
{
void abs_minmax_index(const float *src, size_t count, size_t *min, size_t *max);
}
)

IF_ARCH_AARCH64(
namespace asimd
{
void abs_minmax_index(const float *src, size_t count, size_t *min, size_t *max);
}
)

typedef void (* cond_minmax_t)(const float *src, size_t count, size_t *min, size_t *max);
}

//-----------------------------------------------------------------------------
// Performance test for minimum and maximum searching
PTEST_BEGIN("dsp.search", abs_minmax_index, 5, 1000)

void call(const char *label, const float *in, size_t count, cond_minmax_t func)
{
if (!PTEST_SUPPORTED(func))
return;

char buf[80];
sprintf(buf, "%s x %d", label, int(count));
printf("Testing %s numbers...\n", buf);
size_t min, max;

PTEST_LOOP(buf,
func(in, count, &min, &max);
);
}

PTEST_MAIN
{
size_t buf_size = 1 << MAX_RANK;
uint8_t *data = NULL;

float *in = alloc_aligned<float>(data, buf_size, 64);
for (size_t i=0; i < (1 << MAX_RANK); ++i)
in[i] = randf(-1.0f, 1.0f);

#define CALL(func) \
call(#func, in, count, func)

for (size_t i=MIN_RANK; i <= MAX_RANK; ++i)
{
size_t count = 1 << i;

CALL(generic::abs_minmax_index);
IF_ARCH_X86(CALL(sse2::abs_minmax_index));
IF_ARCH_X86(CALL(avx2::abs_minmax_index));
IF_ARCH_ARM(CALL(neon_d32::abs_minmax_index));
IF_ARCH_AARCH64(CALL(asimd::abs_minmax_index));
PTEST_SEPARATOR;
}

free_aligned(data);
}

PTEST_END


Loading

0 comments on commit 7e6c96c

Please sign in to comment.