This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM275-FREERTOS-SDK: DSPLib cascadeBiquad performance

#include <dsplib.h>


int32_t handleSize = 0;
DSPLIB_kernelHandle handle;
DSPLIB_bufParams2D_t bufParamsIn, bufParamsOut, bufParamsFilterVar;
DSPLIB_bufParams2D_t bufParamsFilterCoeff;
 DSPLIB_bufParams2D_t bufParamsFilterCoeffCn;
DSPLIB_cascadeBiquad_InitArgs kerInitArgs;
bool is_init= false;
int32_t coeffBuffSize = 0;
DSPLIB_STATUS status_coefs = DSPLIB_SUCCESS;
DSPLIB_STATUS status_init = DSPLIB_SUCCESS;
DSPLIB_STATUS status_opt = DSPLIB_SUCCESS;
DSPLIB_STATUS status_init_opt = DSPLIB_SUCCESS;
DSPLIB_STATUS status_exec_opt = DSPLIB_SUCCESS;
float cascadeBiquad_coeff_buff[MAX_EQ_BAND*DSPLIB_NUM_BIQUAD_COEFS] = {0};
float cascadeBiquad_state_buff[MAX_EQ_BAND*DSPLIB_NUM_STATE_VARS_DF1] = {0};



void cascadeBiquadInit()
{
    int eq_band = 15;
    int ch = 1;
        
    handleSize = DSPLIB_cascadeBiquad_getHandleSize(&kerInitArgs);
    handle   = malloc(handleSize);
    kerInitArgs.dataSize    = 64;
	kerInitArgs.numChannels = ch;
	kerInitArgs.numStages   = eq_band;
    kerInitArgs.enableNChCoeffs = 0;
    kerInitArgs.biquadForm        = DSPLIB_BIQUAD_DF1;

    
	//int32_t coeffBuffSize = DSPLIB_cascadeBiquad_get_coefficientsBufferSize(kerInitArgs.numStages);

	

	bufParamsIn.data_type = DSPLIB_FLOAT32;
	bufParamsIn.dim_x     = ch;
    bufParamsIn.dim_y     = 64;
    bufParamsIn.stride_y  = ch*4;

	bufParamsOut.data_type = DSPLIB_FLOAT32;
	bufParamsOut.dim_x     = ch;
    bufParamsOut.dim_y     = 64;
    bufParamsOut.stride_y  = ch*4;


	bufParamsFilterVar.data_type = DSPLIB_FLOAT32;
    bufParamsFilterVar.dim_x      = ch;
	bufParamsFilterVar.dim_y      = eq_band*DSPLIB_NUM_STATE_VARS_DF1; // Five coefficients per stage
    bufParamsFilterVar.stride_y   = ch*4;

    // bufParamsFilterCoeffCn.data_type = DSPLIB_FLOAT32;
    // bufParamsFilterCoeffCn.dim_x     = eq_band * DSPLIB_NUM_BIQUAD_COEFS;
    // bufParamsFilterCoeffCn.dim_y     = 1;
    // bufParamsFilterCoeffCn.stride_y  = bufParamsFilterCoeffCn.dim_x * DSPLIB_sizeof(bufParamsFilterCoeffCn.data_type);

    bufParamsFilterCoeff.data_type = DSPLIB_FLOAT32;
    bufParamsFilterCoeff.dim_x     = eq_band * DSPLIB_NUM_BIQUAD_COEFS;
    bufParamsFilterCoeff.dim_y     = 1;
    bufParamsFilterCoeff.stride_y  = bufParamsFilterCoeff.dim_x * DSPLIB_sizeof(bufParamsFilterCoeff.data_type);


    // Get optimized coefficient buffer descriptor
    status_coefs = DSPLIB_cascadeBiquad_get_coefficientsBufferDesc(DSPLIB_FLOAT32, 
    eq_band, ch, DSPLIB_BIQUAD_DF1, 0, &bufParamsFilterCoeff);
    if (status_coefs != DSPLIB_SUCCESS) {
 
    }
 
}


void filterInit()
{
	
	cascadeBiquadInit();
	for(i=0; i<15; i++)
	{
		for (j=0; j<5; j++) {
			//cascadeBiquad_coeff_buff[i*5+j] = eq->pool.filters[i].coeffs[j];
			cascadeBiquad_coeff_buff[i*5+j] = 0;
		}
		
	}
	kerInitArgs.funcStyle = DSPLIB_FUNCTION_OPTIMIZED;
	status_init = DSPLIB_cascadeBiquad_init_checkParams(handle, &bufParamsIn, &bufParamsFilterCoeff,&bufParamsFilterVar, &bufParamsOut, &kerInitArgs);
	if (status_init_opt == DSPLIB_SUCCESS) {
		status_init_opt = DSPLIB_cascadeBiquad_init(handle, &bufParamsIn, &bufParamsFilterCoeff, &bufParamsFilterVar,
														&bufParamsOut, &kerInitArgs);
	}
}

void filter_process( float * in_data, float *restrict out_data,)
{
	if (status_init_opt == DSPLIB_SUCCESS) 
    {
        status_exec_opt = DSPLIB_cascadeBiquad_exec_checkParams(handle, in_data, cascadeBiquad_coeff_buff, cascadeBiquad_state_buff, out_data);
        if (status_exec_opt == DSPLIB_SUCCESS) {
            status_exec_opt = DSPLIB_cascadeBiquad_exec(handle, in_data, cascadeBiquad_coeff_buff, cascadeBiquad_state_buff, out_data);
            if (status_exec_opt != DSPLIB_SUCCESS) {
                return;
            }
        
        }
    }
}
I downloaded freertos_sdk_am275x_11_01_00_16 and modified some parameters according to DSPLIB_cascadeBiquad_d.c. Currently, the sound effect of 15bands iir is normal, but the cycles count has not decreased. It's almost the same as my implementation in c code. Please refer to test.c for the code.

  • Hi Zhong,
    Can you also share your linker script and the compiler flags you have set? In the meantime, I am also trying to benchmark your code.

    Thanks,
    Shreyansh

  • --ram_model
    -heap  0x8000
    -stack 0x8000
    --args 0x1000
    --diag_suppress=10068 /* to suppress no matching section error */
    --cinit_compression=off
    -e _c_int00_secure
    
    /******************************************************************************/
    /*   The SRAM address is aliased as follows for C7x for enabling CacheWT      */
    /*   SRAM Address       |       Aliased address         |           Size      */
    /*   0x72000000         |        0x80000000             |         0x600000    */
    /******************************************************************************/
    
    MEMORY
    {
        C75_0_L2SRAM (RWX):  org = 0x7E000000,                len = 0x240000
    
        /* Latency will be high while accessing this memory from c75_0 */
        C75_1_L2SRAM (RWX):  org = 0x7F000000,                len = 0x240000
    
        C75_0_OCRAM_ENTRY   (RWIX)   : ORIGIN = 0x80200000 LENGTH = 0x00000080
        C75_0_OCRAM   (RWIX)         : ORIGIN = 0x80200080 LENGTH = 0x00100000 - 0x80 - 0x1000
        C75_0_CIO_MEM                 : ORIGIN = 0x80200040 + 0x00100000 - 0x40 - 0x1000 LENGTH = 0x1000  /* 1MB for c75ss0-0 core */
    
        WKUP_R5_OCRAM (RWIX)         : ORIGIN = 0x80000000 LENGTH = 0x00080000          /* 512 KB for wakeup core */
    
        R50_0_OCRAM   (RWIX)         : ORIGIN = 0x80080000 LENGTH = 0x00100000          /* 1 MB for r5fss0-0 core   */
        R50_1_OCRAM   (RWIX)         : ORIGIN = 0x80180000 LENGTH = 0x00080000          /* 512 KB for r5fss0-1 core */
        R51_0_OCRAM   (RWIX)         : ORIGIN = 0x80300000 LENGTH = 0x00080000          /* 512 KB for r5fss1-0 core */
        R51_1_OCRAM   (RWIX)         : ORIGIN = 0x80380000 LENGTH = 0x00080000          /* 512 KB for r5fss1-1 core */
    
        C75_1_OCRAM   (RWIX)         : ORIGIN = 0x80400000 LENGTH = 0x00080000          /* 512 KB for c75ss1-0 core */
    
    
    }
    
    SECTIONS
    {
        .vecs       >       C75_0_L2SRAM ALIGN(0x200000)
        .text:_c_int00_secure > C75_0_OCRAM_ENTRY ALIGN(0x200000)
        .text       >       C75_0_L2SRAM
    
        .bss        >       C75_0_L2SRAM  /* Zero-initialized data */
        RUN_START(__BSS_START)
        RUN_END(__BSS_END)
    
        .data       >       C75_0_L2SRAM  /* Initialized data */
    
        .cinit      >       C75_0_L2SRAM  /* could be part of const */
        .init_array >       C75_0_L2SRAM  /* C++ initializations */
        .stack      >       C75_0_L2SRAM ALIGN(0x2000)
        .args       >       C75_0_L2SRAM
        .cio        >       C75_0_CIO_MEM
        .const      >       C75_0_L2SRAM
        .switch     >       C75_0_L2SRAM /* For exception handling. */
        .sysmem     >       C75_0_L2SRAM /* heap */
    
        GROUP:              >  C75_0_L2SRAM
        {
            .data.Mmu_tableArray          : type=NOINIT
            .data.Mmu_tableArraySlot      : type=NOINIT
            .data.Mmu_level1Table         : type=NOINIT
            .data.gMmu_tableArray_NS       : type=NOINIT
            .data.Mmu_tableArraySlot_NS   : type=NOINIT
            .data.Mmu_level1Table_NS      : type=NOINIT
        }
    
        .benchmark_buffer:     > C75_0_L2SRAM ALIGN (32)
        .bss.debug_mem_trace_buf:> C75_0_L2SRAM ALIGN (32)
    
    }
    -mv7524 -O4 --opt_for_speed=5 --include_path="C:/TI/ccs2031/ccs/tools/compiler/ti-cgt-c7000_5.0.0.LTS/include" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/kernel/freertos/FreeRTOS-Kernel/include" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/kernel/freertos/portable/TI_CGT/DSP_C75X" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/fs/freertos_fat/portable" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/fs/freertos_fat/FreeRTOS-FAT/include" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/dsplib/src" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/fs/freertos_fat/config" --include_path="C:/TI/freertos_sdk_am275x_11_01_00_16/source/kernel/freertos/config/am275x/c75x" --include_path="E:/TI/workspace/mcasp_multichannel_playback_task_am275x-evm_c75ss0-0_freertos_ti-c7000/Audio" --define=BUILD_C7X --define=BUILD_C7X_1 --define=SOC_AM275X --define=xdc_target_name__=C71 --define=_DEBUG_=1 -g --relaxed_ansi --diag_suppress=238 --diag_suppress=880 --diag_suppress=1110 --diag_suppress=770 --diag_suppress=69 --diag_suppress=70 --diag_warning=225 --diag_wrap=off --display_error_number --emit_warnings_as_errors --quiet --gen_func_subsections=on --disable_inlining --asm_extension=.se71

  • Hi Zhong,
    It looks like you are testing it for single channel. Cascade Biquad implementation has a linear dependency on the previous output, there is no way to use SE/SA in such case, hence for the single channel, you wouldn't see any significant benefit compared to your natural c code. I would expect the kernel to perform much better for higher channel count. Essentially, it would take the same amount of time for single channel and 8 channel input due to the vectorisation across channels.

    Thanks,

    Shreyansh

  • Copy that,thank you.

  • Hi Shreyansh,

    Per we discussed in the internal Email. We know doing multi-channel parallel computation could have further optimizations, that is aligned. However, from our experience supporting other customers, based on single channel architecture we still could have some optimizations by applying the optimized "CI" modules to replace the Natural C. So we need to figure out in this case why customer did not see the improvement after using the "CI" modules, there should be some places that were missing to modify, I think we need spend some time to double check it.

    Thanks,

    Kevin

  • Hi Kevin,
    I will take a look again, however, as i said, there is very little room for optimisation in the case of single channel cascade Biquad.

    Zhong,
    Can you share the cycle count you are seeing for both the natural c and optimised code?

    Thanks,

    Shreyansh

  •  cycle value using dsplib:

    cycle value using c code:  

  • Hi Zhong,
    Is the c code similar to DSPLIB implementation?
    I am getting these numbers:
    Time taken OPT:   22767
    Time taken NATC: 48733

    Your optimised numbers look alright to me. Would it be possible to share the c code?

    Thanks,
    Shreyansh

  • Sorry, I don't have the permission to share the code.

    That is to say, the current performance has been optimized up to now at most.

  • I used optimization level  4.

  • Sorry, I don't have the permission to share the code.

    I understand.

    I made a mistake above in my numbers. I ran my profiling in debug. Here are the results from release mode(O3):
    Time(OPT): 9369
    Time(NATC):42220

    So, your numbers are twice of this. Are you profiling just the exec function or everything?

    Thanks,
    Shreyansh

  • The data just now is the result of the debug version.

    I retested the release version (O4),  cycle value:

    OPT:6330

    NATC:20173

    Thanks

  • Hi Zhong,

    Looks good to me. I will go ahead and close this thread. Please let me know if you have any other questions.

    Thanks,

    Shreyansh

  • Ok, thank you.

    Best wishes