From e0d28c16ce567731a7db196e9ef88e92d948ed9a Mon Sep 17 00:00:00 2001 From: David Reid Date: Sat, 21 Apr 2018 13:31:38 +1000 Subject: [PATCH] Add a simple profiling test. --- tests/mal_profiling.c | 158 +++++++++++++++++++++++++++++++++++++++ tests/mal_test_0.vcxproj | 18 ++--- 2 files changed, 167 insertions(+), 9 deletions(-) diff --git a/tests/mal_profiling.c b/tests/mal_profiling.c index 91da5601..b1fad118 100644 --- a/tests/mal_profiling.c +++ b/tests/mal_profiling.c @@ -1,9 +1,165 @@ #define MAL_IMPLEMENTATION #include "../mini_al.h" +float g_ChannelRouterProfilingOutputBenchmark[8][480000]; +float g_ChannelRouterProfilingOutput[8][480000]; +double g_ChannelRouterTime_Reference = 0; +double g_ChannelRouterTime_SSE2 = 0; +double g_ChannelRouterTime_AVX = 0; +double g_ChannelRouterTime_AVX512 = 0; +double g_ChannelRouterTime_NEON = 0; + +mal_sine_wave sineWave; + +mal_bool32 channel_router_test(mal_uint32 channels, mal_uint64 frameCount, float** ppFramesA, float** ppFramesB) +{ + for (mal_uint32 iChannel = 0; iChannel < channels; ++iChannel) { + for (mal_uint32 iFrame = 0; iFrame < frameCount; ++iFrame) { + if (ppFramesA[iChannel][iFrame] != ppFramesB[iChannel][iFrame]) { + return MAL_FALSE; + } + } + } + + return MAL_TRUE; +} + +mal_uint32 channel_router_on_read(mal_channel_router* pRouter, mal_uint32 frameCount, void** ppSamplesOut, void* pUserData) +{ + (void)pUserData; + (void)pRouter; + + float** ppSamplesOutF = (float**)ppSamplesOut; + + for (mal_uint32 iChannel = 0; iChannel < pRouter->config.channelsIn; ++iChannel) { + mal_sine_wave_init(1/(iChannel+1), 400, 48000, &sineWave); + mal_sine_wave_read(&sineWave, frameCount, ppSamplesOutF[iChannel]); + } + + return frameCount; +} + int do_profiling__channel_routing() { + mal_result result; + // When profiling we need to compare against a benchmark to ensure the optimization is implemented correctly. We always + // use the reference implementation for our benchmark. + mal_uint32 channels = mal_countof(g_ChannelRouterProfilingOutputBenchmark); + mal_channel channelMapIn[MAL_MAX_CHANNELS]; + mal_get_standard_channel_map(mal_standard_channel_map_default, channels, channelMapIn); + mal_channel channelMapOut[MAL_MAX_CHANNELS]; + mal_get_standard_channel_map(mal_standard_channel_map_default, channels, channelMapOut); + + mal_channel_router_config routerConfig = mal_channel_router_config_init(channels, channelMapIn, channels, channelMapOut, mal_channel_mix_mode_planar_blend, channel_router_on_read, NULL); + + mal_channel_router router; + result = mal_channel_router_init(&routerConfig, &router); + if (result != MAL_SUCCESS) { + return -1; + } + + // Disable optimizations for our tests. + router.isPassthrough = MAL_FALSE; + router.isSimpleShuffle = MAL_FALSE; + router.useSSE2 = MAL_FALSE; + router.useAVX = MAL_FALSE; + router.useAVX512 = MAL_FALSE; + router.useNEON = MAL_FALSE; + + mal_uint64 framesToRead = mal_countof(g_ChannelRouterProfilingOutputBenchmark[0]); + + // Benchmark + void* ppOutBenchmark[8]; + for (int i = 0; i < 8; ++i) { + ppOutBenchmark[i] = (void*)g_ChannelRouterProfilingOutputBenchmark[i]; + } + + mal_sine_wave_init(1, 400, 48000, &sineWave); + mal_uint64 framesRead = mal_channel_router_read_deinterleaved(&router, framesToRead, ppOutBenchmark, NULL); + if (framesRead != framesToRead) { + printf("Channel Router: An error occurred while reading benchmark data.\n"); + } + + void* ppOut[8]; + for (int i = 0; i < 8; ++i) { + ppOut[i] = (void*)g_ChannelRouterProfilingOutput[i]; + } + + + printf("Channel Routing\n"); + printf("===============\n"); + + // Reference + { + mal_timer timer; + mal_timer_init(&timer); + double startTime = mal_timer_get_time_in_seconds(&timer); + + framesRead = mal_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); + if (framesRead != framesToRead) { + printf("Channel Router: An error occurred while reading reference data.\n"); + } + + if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { + printf(" [ERROR] "); + } else { + printf(" [PASSED] "); + } + + g_ChannelRouterTime_Reference = mal_timer_get_time_in_seconds(&timer) - startTime; + printf("Reference: %.4fms (%.2f%%)\n", g_ChannelRouterTime_Reference*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_Reference*100); + } + + // SSE2 + if (mal_has_sse2()) { + router.useSSE2 = MAL_TRUE; + mal_timer timer; + mal_timer_init(&timer); + double startTime = mal_timer_get_time_in_seconds(&timer); + + framesRead = mal_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); + if (framesRead != framesToRead) { + printf("Channel Router: An error occurred while reading SSE2 data.\n"); + } + + g_ChannelRouterTime_SSE2 = mal_timer_get_time_in_seconds(&timer) - startTime; + router.useSSE2 = MAL_FALSE; + + if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { + printf(" [ERROR] "); + } else { + printf(" [PASSED] "); + } + + printf("SSE2: %.4fms (%.2f%%)\n", g_ChannelRouterTime_SSE2*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_SSE2*100); + } + + // AVX + if (mal_has_avx()) { + router.useAVX = MAL_TRUE; + mal_timer timer; + mal_timer_init(&timer); + double startTime = mal_timer_get_time_in_seconds(&timer); + + framesRead = mal_channel_router_read_deinterleaved(&router, framesToRead, ppOut, NULL); + if (framesRead != framesToRead) { + printf("Channel Router: An error occurred while reading AVX data.\n"); + } + + g_ChannelRouterTime_AVX = mal_timer_get_time_in_seconds(&timer) - startTime; + router.useAVX = MAL_FALSE; + + if (!channel_router_test(channels, framesRead, (float**)ppOutBenchmark, (float**)ppOut)) { + printf(" [ERROR] "); + } else { + printf(" [PASSED] "); + } + + printf("AVX: %.4fms (%.2f%%)\n", g_ChannelRouterTime_AVX*1000, g_ChannelRouterTime_Reference/g_ChannelRouterTime_AVX*100); + } + + return 1; } int main(int argc, char** argv) @@ -14,5 +170,7 @@ int main(int argc, char** argv) // Channel routing. do_profiling__channel_routing(); + getchar(); + return 0; } \ No newline at end of file diff --git a/tests/mal_test_0.vcxproj b/tests/mal_test_0.vcxproj index 8c81e78d..c81523eb 100644 --- a/tests/mal_test_0.vcxproj +++ b/tests/mal_test_0.vcxproj @@ -259,21 +259,21 @@ - true - true - true - true - true - true - - false - false false + false false false false + + true + true + true + true + true + true + true true