Skip to content

Multi threading #201

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
cmake_minimum_required(VERSION 3.1..3.18)

if (BUILD_MULTI_THREADING)
set(MULTI_THREADING 1)
add_definitions(-DMULTI_THREADING)
endif()

# Policies

# Include file check macros honor CMAKE_REQUIRED_LIBRARIES, CMake >= 3.12
10 changes: 10 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -43,6 +43,16 @@ add_library(samplerate
# ALIAS to use if libsamplerate is included from other project with add_subdirectory()
add_library(SampleRate::samplerate ALIAS samplerate)

if(MULTI_THREADING)
if(MSVC)
target_link_libraries(samplerate PRIVATE libomp)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /openmp:llvm")
else()
target_link_libraries(samplerate PRIVATE omp)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp")
endif()
endif()

# CMake generates wrong DLL names for MinGW and Cygwin, fix it
if(BUILD_SHARED_LIBS AND WIN32)
if(LIBSAMPLERATE_COMPATIBLE_NAME)
652 changes: 652 additions & 0 deletions src/src_sinc.c

Large diffs are not rendered by default.

76 changes: 50 additions & 26 deletions tests/multichan_throughput_test.c
Original file line number Diff line number Diff line change
@@ -36,17 +36,21 @@ static float input [BUFFER_LEN] ;

#if (defined(ENABLE_SINC_FAST_CONVERTER) || defined(ENABLE_SINC_MEDIUM_CONVERTER) || \
defined(ENABLE_SINC_BEST_CONVERTER))
static float output [BUFFER_LEN] ;
static float output [BUFFER_LEN*2] ;

static void
throughput_test (int converter, int channels, long *best_throughput)
throughput_test (int converter, int channels, long *best_throughput, double src_ratio)
{ SRC_DATA src_data ;
#if !defined(_WIN32) && defined(MULTI_THREADING)
struct timespec start_gettime, finish_gettime;
#else
clock_t start_time, clock_time ;
#endif
double duration ;
long total_frames = 0, throughput ;
int error ;

printf (" %-30s %2d ", src_get_name (converter), channels) ;
printf (" %-30s %2d ", src_get_name (converter), channels) ;
fflush (stdout) ;

src_data.data_in = input ;
@@ -55,15 +59,19 @@ throughput_test (int converter, int channels, long *best_throughput)
src_data.data_out = output ;
src_data.output_frames = ARRAY_LEN (output) / channels ;

src_data.src_ratio = 0.99 ;
src_data.src_ratio = src_ratio ;

#ifdef _WIN32
Sleep (2000) ;
#else
sleep (2) ;
#endif

#if !defined(_WIN32) && defined(MULTI_THREADING)
clock_gettime(CLOCK_MONOTONIC, &start_gettime);
#else
start_time = clock () ;
#endif

do
{
@@ -74,28 +82,37 @@ throughput_test (int converter, int channels, long *best_throughput)

total_frames += src_data.output_frames_gen ;

#if !defined(_WIN32) && defined(MULTI_THREADING)
clock_gettime(CLOCK_MONOTONIC, &finish_gettime);

duration = (finish_gettime.tv_sec - start_gettime.tv_sec);
duration += (finish_gettime.tv_nsec - start_gettime.tv_nsec) / 1000000000.0;
#else
clock_time = clock () - start_time ;
duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
#endif
}
while (duration < 5.0) ;

if (src_data.input_frames_used != src_data.input_frames)
{ printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ;
exit (1) ;
} ;

if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
printf (" input len : %d\n", ARRAY_LEN (input) / channels) ;
printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
exit (1) ;
} ;
if ( src_ratio <= 1.0 ){
if (src_data.input_frames_used != src_data.input_frames)
{ printf ("\n\nLine %d : input frames used %ld should be %ld\n", __LINE__, src_data.input_frames_used, src_data.input_frames) ;
exit (1) ;
} ;

if (fabs (src_data.src_ratio * src_data.input_frames_used - src_data.output_frames_gen) > 2)
{ printf ("\n\nLine %d : input / output length mismatch.\n\n", __LINE__) ;
printf (" input len : %d\n", ARRAY_LEN (input) / channels) ;
printf (" output len : %ld (should be %g +/- 2)\n\n", src_data.output_frames_gen,
floor (0.5 + src_data.src_ratio * src_data.input_frames_used)) ;
exit (1) ;
} ;
}

throughput = lrint (floor (total_frames / duration)) ;

if (!best_throughput)
{ printf ("%5.2f %10ld\n", duration, throughput) ;
{ printf ("%5.2f %10ld (x%7.2f)\n", duration, throughput, (throughput/src_ratio/44100)) ;
}
else
{ *best_throughput = MAX (throughput, *best_throughput) ;
@@ -116,31 +133,38 @@ single_run (void)

printf ("\n CPU name : %s\n", get_cpu_name ()) ;

double src_ratio[] = {0.99, 2.0, 7.0, 0.25};

for( int i=0 ; i<sizeof(src_ratio)/sizeof(double) ; i++ ){
printf ("\n SRC_RATIO : %.2lf\n", src_ratio[i]) ;

puts (
"\n"
" Converter Channels Duration Throughput\n"
" ---------------------------------------------------------------------"
" Converter Ch Duration Throughput (times faster than realtime if 44.1k in)\n"
" -------------------------------------------------------------------------"
) ;

#ifdef ENABLE_SINC_FAST_CONVERTER
for (k = 1 ; k <= max_channels / 2 ; k++)
throughput_test (SRC_SINC_FASTEST, k, 0) ;
throughput_test (SRC_SINC_FASTEST, k, 0, src_ratio[i]) ;

puts ("") ;
#endif

#ifdef ENABLE_SINC_MEDIUM_CONVERTER
for (k = 1 ; k <= max_channels / 2 ; k++)
throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0) ;
throughput_test (SRC_SINC_MEDIUM_QUALITY, k, 0, src_ratio[i]) ;

puts ("") ;
#endif

#ifdef ENABLE_SINC_BEST_CONVERTER
for (k = 1 ; k <= max_channels ; k++)
throughput_test (SRC_SINC_BEST_QUALITY, k, 0) ;
throughput_test (SRC_SINC_BEST_QUALITY, k, 0, src_ratio[i]) ;
puts ("") ;
#endif

}
return ;
} /* single_run */

@@ -152,7 +176,7 @@ multi_run (int run_count)

puts (
"\n"
" Converter Channels Duration Throughput Best Throughput\n"
" Converter Ch Duration Throughput Best Throughput\n"
" ----------------------------------------------------------------------------------------"
) ;

@@ -172,13 +196,13 @@ multi_run (int run_count)
for (int k = 0 ; k < run_count ; k++)
{
#ifdef ENABLE_SINC_FAST_CONVERTER
throughput_test (SRC_SINC_FASTEST, ch, &sinc_fastest) ;
throughput_test (SRC_SINC_FASTEST, ch, &sinc_fastest, 0.99) ;
#endif
#ifdef ENABLE_SINC_MEDIUM_CONVERTER
throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, &sinc_medium) ;
throughput_test (SRC_SINC_MEDIUM_QUALITY, ch, &sinc_medium, 0.99) ;
#endif
#ifdef ENABLE_SINC_BEST_CONVERTER
throughput_test (SRC_SINC_BEST_QUALITY, ch, &sinc_best) ;
throughput_test (SRC_SINC_BEST_QUALITY, ch, &sinc_best, 0.99) ;
#endif

puts ("") ;
15 changes: 15 additions & 0 deletions tests/throughput_test.c
Original file line number Diff line number Diff line change
@@ -38,7 +38,11 @@ static float output [BUFFER_LEN] ;
static long
throughput_test (int converter, long best_throughput)
{ SRC_DATA src_data ;
#if !defined(_WIN32) && defined(MULTI_THREADING)
struct timespec start_gettime, finish_gettime;
#else
clock_t start_time, clock_time ;
#endif
double duration ;
long total_frames = 0, throughput ;
int error ;
@@ -60,7 +64,11 @@ throughput_test (int converter, long best_throughput)
sleep (2) ;
#endif

#if !defined(_WIN32) && defined(MULTI_THREADING)
clock_gettime(CLOCK_MONOTONIC, &start_gettime);
#else
start_time = clock () ;
#endif

do
{
@@ -71,11 +79,18 @@ throughput_test (int converter, long best_throughput)

total_frames += src_data.output_frames_gen ;

#if !defined(_WIN32) && defined(MULTI_THREADING)
clock_gettime(CLOCK_MONOTONIC, &finish_gettime);

duration = (finish_gettime.tv_sec - start_gettime.tv_sec);
duration += (finish_gettime.tv_nsec - start_gettime.tv_nsec) / 1000000000.0;
#else
clock_time = clock () - start_time ;
#ifdef __GNU__ /* Clock resolution is 10ms on GNU/Hurd */
duration = (10000.0 * clock_time) / CLOCKS_PER_SEC ;
#else
duration = (1.0 * clock_time) / CLOCKS_PER_SEC ;
#endif
#endif
}
while (duration < 3.0) ;