mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2026-06-16 04:32:47 +02:00
21ac0b276e
To reproduce this commit, run: $ git subtree add --squash --prefix=tests/checkasm/ext \ https://code.ffmpeg.org/FFmpeg/checkasm.git master To update at a later point in time, replace `add` by `pull`
281 lines
7.8 KiB
Markdown
281 lines
7.8 KiB
Markdown
@page getting_started Getting Started
|
|
|
|
This guide will walk you through installing checkasm and writing your first test.
|
|
|
|
@tableofcontents
|
|
|
|
@section installation Installation
|
|
|
|
You can either load checkasm as a library (e.g. via `pkg-config`), or include it directly in your project's build system.
|
|
|
|
@subsection meson_submodules Meson using wrap files (recommended)
|
|
|
|
First, create `subprojects/checkasm.wrap`:
|
|
|
|
@code{.ini}
|
|
[wrap-git]
|
|
url = https://code.videolan.org/videolan/checkasm.git
|
|
revision = release # or a specific tag/release
|
|
directory = checkasm
|
|
@endcode
|
|
|
|
Then integrate it into your build system:
|
|
|
|
@code{.meson}
|
|
# This first attempts loading checkasm as an external dependency using the
|
|
# appropriate platform-specific method (e.g. pkg-config on POSIX systems),
|
|
# and falls back to using the bundled version inside `subprojects/checkasm`
|
|
# otherwise.
|
|
checkasm_dependency = dependency('checkasm',
|
|
# Extracts the `checkasm_dep` variable from the `checkasm` subproject.
|
|
fallback: ['checkasm', 'checkasm_dep'],
|
|
required: false
|
|
)
|
|
|
|
# Alternatively, you can directly force use of the bundled version:
|
|
# checkasm_dependency = subproject('checkasm').get_variable('checkasm_dep')
|
|
|
|
if checkasm_dependency.found()
|
|
checkasm = executable('checkasm',
|
|
checkasm_sources,
|
|
dependencies: checkasm_dependency,
|
|
)
|
|
|
|
test('checkasm', checkasm, suite: 'checkasm')
|
|
benchmark('checkasm', checkasm, suite: 'checkasm', args: '--bench')
|
|
endif
|
|
@endcode
|
|
|
|
@subsection meson_wrap Meson using submodules (alternative)
|
|
|
|
As an alternative, you may use git submodules to include checkasm as a subproject.
|
|
This may be preferred in some environments where the build system cannot access
|
|
the internet during configuration time, or if you're already using submodules
|
|
in your project.
|
|
|
|
@code{.bash}
|
|
git submodule init
|
|
git submodule add -b release https://code.videolan.org/videolan/checkasm subprojects/checkasm
|
|
# or checkout a specific tag/release
|
|
@endcode
|
|
|
|
Then declare the dependency in your `meson.build` as usual. (See the previous section)
|
|
|
|
@subsection manual_installation Manual Installation
|
|
|
|
You can also build and install checkasm manually:
|
|
|
|
@code{.bash}
|
|
git clone https://github.com/videolan/checkasm.git && cd checkasm
|
|
meson setup builddir -Dprefix=$PREFIX # (set optional build prefix)
|
|
meson compile -C builddir
|
|
meson install -C builddir
|
|
@endcode
|
|
|
|
This is discouraged in favor of using Meson subprojects or distribution packages,
|
|
but may be useful inside containerized environments, CI systems or custom
|
|
build roots.
|
|
|
|
@section quick_start Quick Start Example
|
|
|
|
Let's create a simple test for a vector addition function that operates on buffers.
|
|
|
|
@subsection quick_start1 1. Prerequisites
|
|
|
|
Let's assume you have a reference implementation and an optimized version,
|
|
alongside a way of detecting CPU features and choosing the implementation
|
|
based on that:
|
|
|
|
@code{.h}
|
|
// my_dsp.h
|
|
#include <stdint.h>
|
|
|
|
enum {
|
|
CPU_FLAG_AVX = 1 << 0,
|
|
};
|
|
|
|
unsigned detect_cpu_flags(void);
|
|
|
|
typedef void (*add8_func_t)(uint16_t *dst, const uint8_t *src1,
|
|
const uint8_t *src2, size_t len);
|
|
|
|
add8_func_t get_add8_func(unsigned cpu_flags);
|
|
@endcode
|
|
|
|
@code{.c}
|
|
// my_dsp.c
|
|
|
|
#include "my_cpu.h"
|
|
|
|
// Reference implementation (pure C)
|
|
static void add8_c(uint16_t *dst, const uint8_t *src1,
|
|
const uint8_t *src2, size_t len)
|
|
{
|
|
for (size_t i = 0; i < len; i++)
|
|
dst[i] = src1[i] + src2[i];
|
|
}
|
|
|
|
// Optimized implementation (pretend this is assembly)
|
|
static void add8_avx(uint16_t *dst, const uint8_t *src1,
|
|
const uint8_t *src2, size_t len)
|
|
{
|
|
// Assembly optimized version would go here
|
|
add8_c(dst, src1, src2, len);
|
|
}
|
|
|
|
add8_func_t get_add8_func(unsigned cpu_flags)
|
|
{
|
|
if (cpu_flags & CPU_FLAG_AVX)
|
|
return add8_avx;
|
|
return add8_c;
|
|
}
|
|
@endcode
|
|
|
|
@subsection quick_start2 2. Write the Test
|
|
|
|
Create your test file:
|
|
|
|
@code{.c}
|
|
// check_dsp.c
|
|
|
|
#include <checkasm/checkasm.h>
|
|
#include <checkasm/test.h>
|
|
|
|
#include "my_dsp.h"
|
|
|
|
#define WIDTH 1024
|
|
|
|
static void test_add8(const CheckasmCpu cpu)
|
|
{
|
|
// Declare aligned buffers for testing
|
|
CHECKASM_ALIGN(uint8_t src1[WIDTH]);
|
|
CHECKASM_ALIGN(uint8_t src2[WIDTH]);
|
|
CHECKASM_ALIGN(uint16_t dst_c[WIDTH]);
|
|
CHECKASM_ALIGN(uint16_t dst_a[WIDTH]);
|
|
|
|
// Declare the function signature
|
|
checkasm_declare(void, uint16_t *, const uint8_t *, const uint8_t *, size_t);
|
|
|
|
if (checkasm_check_func(get_add8_func(cpu), "add_8")) {
|
|
// Initialize source buffers with quasi-random test vectors
|
|
INITIALIZE_BUF(src1);
|
|
INITIALIZE_BUF(src2);
|
|
|
|
// Test with various buffer sizes
|
|
for (int w = 1; w <= WIDTH; w <<= 1) {
|
|
// Clear destination buffers before each test
|
|
CLEAR_BUF(dst_c);
|
|
CLEAR_BUF(dst_a);
|
|
|
|
// Call reference and optimized implementations
|
|
checkasm_call_ref(dst_c, src1, src2, w);
|
|
checkasm_call_new(dst_a, src1, src2, w);
|
|
|
|
// Compare results - checkasm_check1d will report any mismatches
|
|
checkasm_check1d(uint16_t, dst_c, dst_a, w, "sum");
|
|
}
|
|
|
|
// Benchmark the optimized version on the largest buffer size
|
|
checkasm_bench_new(checkasm_alternate(dst_c, dst_a), src1, src2, WIDTH);
|
|
}
|
|
}
|
|
|
|
static void check_dsp(void)
|
|
{
|
|
const CheckasmCpu cpu = checkasm_get_cpu_flags();
|
|
|
|
// Test all related functions and report as a single function group
|
|
test_add8(cpu);
|
|
// test_add16(cpu);
|
|
// ...
|
|
checkasm_report("add");
|
|
|
|
// Check more function groups
|
|
// ...
|
|
}
|
|
|
|
// Test registry
|
|
static const CheckasmTest tests[] = {
|
|
{ "dsp", check_dsp },
|
|
{0} // array terminator
|
|
};
|
|
|
|
// CPU flag registry
|
|
static const CheckasmCpuInfo cpu_flags[] = {
|
|
{ "AVX", "avx", CPU_FLAG_AVX },
|
|
{0} // array terminator
|
|
};
|
|
|
|
int main(int argc, const char *argv[]) {
|
|
CheckasmConfig config = {
|
|
.tests = tests,
|
|
.cpu_flags = cpu_flags,
|
|
.cpu = detect_cpu_flags(),
|
|
};
|
|
|
|
return checkasm_main(&config, argc, argv);
|
|
}
|
|
@endcode
|
|
|
|
@subsection quick_start3 3. Build and Run
|
|
|
|
@code{.bash}
|
|
# Compile (example using gcc directly)
|
|
gcc -o check_dsp my_dsp.c check_dsp.c $(pkg-config --cflags --libs checkasm)
|
|
# or use `meson compile` if using Meson
|
|
|
|
# Run all tests
|
|
./check_dsp
|
|
@endcode
|
|
|
|
@section options Command-Line Options
|
|
|
|
checkasm provides several useful command-line options:
|
|
|
|
@code{.bash}
|
|
# List all available functions
|
|
./checkasm --list-functions
|
|
|
|
# Run specific functions (supports wildcards)
|
|
./checkasm --function=add_*_8bpc
|
|
|
|
# Run benchmarks
|
|
./checkasm --bench
|
|
|
|
# Run specified test with higher benchmark duration (here: 10 ms)
|
|
./checkasm --test=pixel --bench --duration=10000
|
|
|
|
# Enable verbose output
|
|
./checkasm --verbose
|
|
@endcode
|
|
|
|
The `--help` output shows all available options:
|
|
|
|
@code{.txt}
|
|
Usage: checkasm [options...] <random seed>
|
|
<random seed> Use fixed value to seed the PRNG
|
|
Options:
|
|
--affinity=<cpu> Run the process on CPU <cpu>
|
|
--bench -b Benchmark the tested functions
|
|
--csv, --tsv, --json, Choose output format for benchmarks
|
|
--html
|
|
--function=<pattern> -f Test only the functions matching <pattern>
|
|
--help -h Print this usage info
|
|
--list-cpu-flags List available cpu flags
|
|
--list-functions List available functions
|
|
--list-tests List available tests
|
|
--duration=<μs> Benchmark duration (per function) in μs
|
|
--repeat[=<N>] Repeat tests N times, on successive seeds
|
|
--test=<pattern> -t Test only <pattern>
|
|
--verbose -v Print verbose timing info and failure data
|
|
@endcode
|
|
|
|
---
|
|
|
|
@section getting_started_next_steps Next Steps
|
|
|
|
Now that you've set up checkasm and written your first test, learn how to
|
|
integrate it properly with your project's CPU detection and dispatch mechanisms.
|
|
|
|
**Next:** @ref integration
|