Changeset 849

Show
Ignore:
Timestamp:
01/16/08 14:19:48 (15 years ago)
Author:
ppalmers
Message:

temp commit of some SSE/memory optimizations

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libffado/SConstruct

    r847 r849  
    330330    print "Doing an optimized build..." 
    331331 
     332#>>!!!!!!!HACK!!!!!! 
     333env.AppendUnique( CCFLAGS=["-msse2"] ) 
     334env.AppendUnique( CFLAGS=["-msse2"] ) 
     335#<<!!!!!!!HACK!!!!!! 
    332336 
    333337env['REVISION'] = os.popen('svnversion .').read()[:-1] 
  • trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.cpp

    r847 r849  
    2525#include "AmdtpTransmitStreamProcessor.h" 
    2626#include "AmdtpPort.h" 
     27#include "AmdtpBufferOps.h" 
    2728#include "../StreamProcessorManager.h" 
    2829#include "devicemanager.h" 
     
    3839 
    3940#include "libutil/ByteSwap.h" 
    40  
    41 #define AMDTP_FLOAT_MULTIPLIER 2147483392.0 
    4241 
    4342namespace Streaming 
     
    409408        unsigned int nevents, unsigned int offset ) 
    410409{ 
     410    // update the variable parts of the cache 
    411411    updatePortCache(); 
     412 
     413    // encode audio data 
     414    // the data is stored in the original format (float, int). later on 
     415    // the complete buffer is converted to the correct type and labeled at once 
     416    muxAudioPorts((quadlet_t *)data, offset, nevents); 
     417 
     418    // label everything as MBLA audio since those are by far the most 
     419    // occurring. If we treat all as audio we can use efficient block 
     420    // processing. Afterwards we can correct wrong labels of other 
     421    // types. 
    412422    switch(m_StreamProcessorManager.getAudioDataType()) { 
    413423        case StreamProcessorManager::eADT_Int24: 
    414             encodeAudioPortsInt24((quadlet_t *)data, offset, nevents); 
     424            convertFromInt24AndLabelAsMBLA(((quadlet_t *)data), nevents * m_dimension); 
    415425            break; 
    416426        case StreamProcessorManager::eADT_Float: 
    417             encodeAudioPortsFloat((quadlet_t *)data, offset, nevents); 
     427            convertFromFloatAndLabelAsMBLA(((quadlet_t *)data), nevents * m_dimension); 
    418428            break; 
    419429    } 
     430 
     431    // do midi ports 
    420432    encodeMidiPorts((quadlet_t *)data, offset, nevents); 
     433    // do endian conversion 
    421434    byteSwapToBus(((quadlet_t *)data), nevents * m_dimension); 
    422435    return true; 
     
    431444 
    432445    encodeAudioPortsSilence((quadlet_t *)data, offset, nevents); 
     446    convertFromInt24AndLabelAsMBLA(((quadlet_t *)data), nevents * m_dimension); 
    433447    encodeMidiPortsSilence((quadlet_t *)data, offset, nevents); 
    434448    byteSwapToBus(((quadlet_t *)data), nevents * m_dimension); 
     
    457471        for (j = 0;j < nevents; j += 1) 
    458472        { 
    459             *target_event = 0x40000000
     473            *target_event = 0
    460474            target_event += m_dimension; 
    461475            __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
     
    464478} 
    465479 
     480#ifdef __SSE2__ 
     481//#if 0 
     482#include <emmintrin.h> 
     483#warning SSE2 build 
     484 
    466485/** 
    467  * @brief encodes all audio ports in the cache to events (float data) 
     486 * @brief mux all audio ports to events 
    468487 * @param data  
    469488 * @param offset  
     
    471490 */ 
    472491void 
    473 AmdtpTransmitStreamProcessor::encodeAudioPortsFloat(quadlet_t *data, 
    474                                                     unsigned int offset, 
    475                                                     unsigned int nevents) 
     492AmdtpTransmitStreamProcessor::muxAudioPorts(quadlet_t *data, 
     493                                            unsigned int offset, 
     494                                            unsigned int nevents) 
    476495{ 
    477496    unsigned int j; 
     
    479498    unsigned int i; 
    480499 
    481     for (i = 0; i < m_nb_audio_ports; i++) { 
     500    quadlet_t * client_buffers[4]; 
     501    quadlet_t tmp_values[4] __attribute__ ((aligned (16))); 
     502 
     503    // prepare the scratch buffer 
     504    assert(m_scratch_buffer_size_bytes > nevents * 4); 
     505    memset(m_scratch_buffer, 0, nevents * 4); 
     506     
     507    // this assumes that audio ports are sorted by position, 
     508    // and that there are no gaps 
     509    for (i = 0; i < m_nb_audio_ports-4; i += 4) { 
     510        struct _MBLA_port_cache *p; 
     511 
     512        // get the port buffers 
     513        for (j=0; j<4; j++) { 
     514            p = &(m_audio_ports.at(i+j)); 
     515            if(p->buffer && p->enabled) { 
     516                client_buffers[j] = (quadlet_t *) p->buffer; 
     517                client_buffers[j] += offset; 
     518            } else { 
     519                // if a port is disabled or has no valid 
     520                // buffer, use the scratch buffer (all zero's) 
     521                client_buffers[j] = (quadlet_t *) m_scratch_buffer; 
     522            } 
     523        } 
     524 
     525        // the base event for this position 
     526        target_event = (quadlet_t *)(data + i); 
     527 
     528        // process the events 
     529        for (j=0;j < nevents; j += 1) 
     530        { 
     531            // read the values 
     532            tmp_values[0] = *(client_buffers[0]); 
     533            tmp_values[1] = *(client_buffers[1]); 
     534            tmp_values[2] = *(client_buffers[2]); 
     535            tmp_values[3] = *(client_buffers[3]); 
     536 
     537            // convert to packed int 
     538            __m128i v_vals = *((__m128i*)tmp_values); 
     539            __m128i *target = (__m128i*)target_event; 
     540 
     541            // store the packed int 
     542            // (target misalignment is assumed since we don't know the m_dimension) 
     543            _mm_storeu_si128 (target, v_vals); 
     544 
     545            // increment the buffer pointers 
     546            client_buffers[0]++; 
     547            client_buffers[1]++; 
     548            client_buffers[2]++;  
     549            client_buffers[3]++; 
     550 
     551            // go to next target event position 
     552            target_event += m_dimension; 
     553        } 
     554    } 
     555 
     556    // do remaining ports 
     557    for (; i < m_nb_audio_ports; i++) { 
    482558        struct _MBLA_port_cache &p = m_audio_ports.at(i); 
    483559        target_event = (quadlet_t *)(data + i); 
    484         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
    485560        assert(nevents + offset <= p.buffer_size ); 
    486561 
    487562        if(p.buffer && p.enabled) { 
    488             float *buffer = (float *)(p.buffer); 
     563            quadlet_t *buffer = (quadlet_t *)(p.buffer); 
    489564            buffer += offset; 
    490             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 
    491565     
    492566            for (j = 0;j < nevents; j += 1) 
    493567            { 
    494                 // don't care for overflow 
    495                 float v = (*buffer) * AMDTP_FLOAT_MULTIPLIER; 
    496                 unsigned int tmp = ((int) v); 
    497                 *target_event = ( tmp >> 8 ) | 0x40000000; 
     568                *target_event = *buffer; 
    498569                buffer++; 
    499                 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 
    500570                target_event += m_dimension; 
    501                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
    502571            } 
    503572        } else { 
    504573            for (j = 0;j < nevents; j += 1) 
    505574            { 
    506                 *target_event = 0x40000000; 
     575                *target_event = 0x0; 
    507576                target_event += m_dimension; 
    508                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
    509             } 
    510         } 
    511     } 
    512 
     577            } 
     578        } 
     579    } 
     580
     581 
     582#else 
    513583 
    514584/** 
    515  * @brief encodes all audio ports in the cache to events (int24 data) 
     585 * @brief mux all audio ports to events 
    516586 * @param data  
    517587 * @param offset  
     
    519589 */ 
    520590void 
    521 AmdtpTransmitStreamProcessor::encodeAudioPortsInt24(quadlet_t *data, 
    522                                                     unsigned int offset, 
    523                                                     unsigned int nevents) 
     591AmdtpTransmitStreamProcessor::muxAudioPorts(quadlet_t *data, 
     592                                            unsigned int offset, 
     593                                            unsigned int nevents) 
    524594{ 
    525595    unsigned int j; 
     
    530600        struct _MBLA_port_cache &p = m_audio_ports.at(i); 
    531601        target_event = (quadlet_t *)(data + i); 
    532         __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
    533602        assert(nevents + offset <= p.buffer_size ); 
    534603 
    535604        if(p.buffer && p.enabled) { 
    536             uint32_t *buffer = (uint32_t *)(p.buffer); 
     605            quadlet_t *buffer = (quadlet_t *)(p.buffer); 
    537606            buffer += offset; 
    538             __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 
    539  
    540             for (j = 0; j < nevents; j += 1) 
     607     
     608            for (j = 0;j < nevents; j += 1) 
    541609            { 
    542                 *target_event = ((*buffer) & 0x00FFFFFF) | 0x40000000
     610                *target_event = *buffer
    543611                buffer++; 
    544                 __builtin_prefetch(buffer, 0, 0); // prefetch events for read, no temporal locality 
    545  
    546612                target_event += m_dimension; 
    547                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
    548613            } 
    549614        } else { 
    550615            for (j = 0;j < nevents; j += 1) 
    551616            { 
    552                 *target_event = 0x40000000; 
     617                *target_event = 0x0; 
    553618                target_event += m_dimension; 
    554                 __builtin_prefetch(target_event, 1, 0); // prefetch events for write, no temporal locality 
    555            
    556        
    557    
    558 
     619            } 
     620       
     621   
     622
     623#endif 
    559624 
    560625/** 
  • trunk/libffado/src/libstreaming/amdtp/AmdtpTransmitStreamProcessor.h

    r833 r849  
    120120    void encodeMidiPortsSilence(quadlet_t *data, unsigned int offset, unsigned int nevents); 
    121121    void encodeMidiPorts(quadlet_t *data, unsigned int offset, unsigned int nevents); 
     122    void muxAudioPorts(quadlet_t *data, unsigned int offset, unsigned int nevents); 
    122123 
    123124    unsigned int getFDF(); 
  • trunk/libffado/src/libutil/ByteSwap.h

    r847 r849  
    2626 
    2727#include <netinet/in.h> 
     28#include <endian.h> 
    2829#include <assert.h> 
    2930 
     
    3334#include <stdio.h> 
    3435 
     36#if __BYTE_ORDER == __BIG_ENDIAN 
     37 
     38// no-op for big endian machines 
     39static inline void 
     40byteSwapToBus(quadlet_t *data, unsigned int nb_elements) 
     41{ 
     42    return; 
     43} 
     44 
     45static inline void 
     46byteSwapFromBus(quadlet_t *data, unsigned int nb_elements) 
     47{ 
     48    return; 
     49} 
     50 
     51#else 
     52 
    3553#ifdef __SSE2__ 
    3654#include <emmintrin.h> 
    3755#warning SSE2 build 
    3856 
    39 static inline void 
     57//static inline void 
     58void 
    4059byteSwapToBus(quadlet_t *data, unsigned int nb_elements) 
    4160{ 
     
    85104} 
    86105 
    87 static inline void 
     106//static inline void 
     107void 
    88108byteSwapFromBus(quadlet_t *data, unsigned int nb_elements) 
    89109{ 
     
    109129    __m128i v; 
    110130    while(nb_elements >= 4) { 
    111         // prefetch the data for the next round 
    112          __builtin_prefetch(data+128, 0, 0); 
    113  
    114131        // load the data into the vector unit 
    115132        v = _mm_load_si128((__m128i*)data); 
     
    155172} 
    156173 
    157 #endif 
     174#endif // sse2 
    158175 
    159 #endif 
     176#endif // byte order 
     177 
     178#endif // h 
  • trunk/libffado/tests/test-bufferops.cpp

    r847 r849  
    2727 
    2828#include "libutil/ByteSwap.h" 
     29#include "libstreaming/amdtp/AmdtpBufferOps.h" 
     30 
    2931#include "libutil/SystemTimeSource.h" 
    3032#include <inttypes.h> 
    3133 
    32 #include <emmintrin.h> 
    33 /* 
    34 void test() { 
    35     vSInt16     *in, *out; //must be 16 byte aligned 
    36  
    37     for( x = 0; x < array_bytes / sizeof( vSInt16); x++ ) 
    38     { 
    39         vSInt16 v = in[x]; //load 16 bytes 
    40         v = _mm_or_si128( _mm_slli_epi16( v, 8 ), _mm_srli_epi16( v, 8 ) ); //swap it 
    41         out[x] = v; //store it out 
    42     } 
    43 }*/ 
    44  
    45 #define NB_QUADLETS (4096 * 4096) 
     34// 32M of test data 
     35#define NB_QUADLETS (1024 * 1024 * 32) 
    4636#define NB_TESTS 10 
    47 int 
    48 main(int argc, char **argv) { 
     37 
     38bool 
     39testByteSwap(int nb_quadlets, int nb_tests) { 
    4940    quadlet_t *buffer_1; 
    5041    quadlet_t *buffer_ref; 
     
    5748    setDebugLevel(DEBUG_LEVEL_NORMAL); 
    5849     
    59     buffer_1 = new quadlet_t[NB_QUADLETS]; 
    60     buffer_ref = new quadlet_t[NB_QUADLETS]; 
    61      
    62     debugOutput(DEBUG_LEVEL_NORMAL, "Generating test data...\n"); 
    63     for (i=0; i<NB_QUADLETS; i++) { 
     50    buffer_1 = new quadlet_t[nb_quadlets]; 
     51    buffer_ref = new quadlet_t[nb_quadlets]; 
     52     
     53    printMessage( "Generating test data...\n"); 
     54    for (i=0; i<nb_quadlets; i++) { 
    6455        byte_t tmp = i & 0xFF; 
    6556        buffer_1[i]   = tmp << 24; 
     
    7465    // do reference conversion 
    7566     
    76     for (i=0; i<NB_QUADLETS; i++) { 
     67    for (i=0; i<nb_quadlets; i++) { 
    7768        buffer_ref[i] = htonl(buffer_1[i]); 
    7869    } 
    7970     
    80     debugOutput(DEBUG_LEVEL_NORMAL, "Performing byte-swap...\n"); 
     71    printMessage( "Performing byte-swap...\n"); 
    8172     
    8273    int test=0; 
    83     for (test=0; test<NB_TESTS; test++) { 
    84         for (i=0; i<NB_QUADLETS; i++) { 
     74    for (test=0; test<nb_tests; test++) { 
     75        for (i=0; i<nb_quadlets; i++) { 
    8576            byte_t tmp = i & 0xFF; 
    8677            buffer_1[i]   = tmp << 24; 
     
    9485 
    9586        start = time.getCurrentTimeAsUsecs(); 
    96         byteSwapToBus(buffer_1, NB_QUADLETS); 
     87        byteSwapToBus(buffer_1, nb_quadlets); 
    9788        elapsed = time.getCurrentTimeAsUsecs() - start; 
    98         debugOutput(DEBUG_LEVEL_NORMAL, " took %lluusec...\n", elapsed); 
     89        printMessage( " took %lluusec...\n", elapsed); 
    9990         
    10091    } 
    10192 
    10293    // check 
    103     debugOutput(DEBUG_LEVEL_NORMAL, "Checking results...\n"); 
     94    printMessage( "Checking results...\n"); 
    10495    bool all_ok=true; 
    105     for (i=0; i<NB_QUADLETS; i++) { 
     96    for (i=0; i<nb_quadlets; i++) { 
    10697        if (buffer_1[i] != buffer_ref[i]) { 
    107             debugOutput(DEBUG_LEVEL_NORMAL, " bad result: %08X should be %08X\n", 
     98            printMessage( " bad result: %08X should be %08X\n", 
    10899                        buffer_1[i], buffer_ref[i]); 
    109100            all_ok=false; 
     
    116107    delete[] buffer_1; 
    117108    delete[] buffer_ref; 
     109    return all_ok; 
     110} 
     111 
     112bool 
     113testInt24Label(int nb_quadlets, int nb_tests) { 
     114    quadlet_t *buffer_1; 
     115    quadlet_t *buffer_ref; 
     116    int i=0; 
     117     
     118    Util::SystemTimeSource time; 
     119    ffado_microsecs_t start; 
     120    ffado_microsecs_t elapsed; 
     121     
     122    setDebugLevel(DEBUG_LEVEL_MESSAGE); 
     123     
     124    buffer_1 = new quadlet_t[nb_quadlets]; 
     125    buffer_ref = new quadlet_t[nb_quadlets]; 
     126     
     127    printMessage( "Generating test data...\n"); 
     128    for (i=0; i<nb_quadlets; i++) { 
     129        byte_t tmp = i & 0xFF; 
     130        buffer_1[i]   = tmp << 16; 
     131        tmp = (i + 1) & 0xFF; 
     132        buffer_1[i]   |= tmp << 8; 
     133        tmp = (i + 2) & 0xFF; 
     134        buffer_1[i]   |= tmp; 
     135    } 
     136     
     137    // do reference conversion 
     138    for (i=0; i<nb_quadlets; i++) { 
     139        buffer_ref[i] = buffer_1[i] | 0x40000000; 
     140    } 
     141     
     142    printMessage( "Performing AMDTP labeling...\n"); 
     143     
     144    int test=0; 
     145    for (test=0; test<nb_tests; test++) { 
     146        for (i=0; i<nb_quadlets; i++) { 
     147            byte_t tmp = i & 0xFF; 
     148            buffer_1[i]   = tmp << 16; 
     149            tmp = (i + 1) & 0xFF; 
     150            buffer_1[i]   |= tmp << 8; 
     151            tmp = (i + 2) & 0xFF; 
     152            buffer_1[i]   |= tmp; 
     153        } 
     154 
     155        start = time.getCurrentTimeAsUsecs(); 
     156        convertFromInt24AndLabelAsMBLA(buffer_1, nb_quadlets); 
     157        elapsed = time.getCurrentTimeAsUsecs() - start; 
     158        printMessage( " took %lluusec...\n", elapsed); 
     159    } 
     160 
     161    // check 
     162    printMessage( "Checking results...\n"); 
     163    bool all_ok=true; 
     164    for (i=0; i<nb_quadlets; i++) { 
     165        if (buffer_1[i] != buffer_ref[i]) { 
     166            printMessage( " bad result: %08X should be %08X\n", 
     167                        buffer_1[i], buffer_ref[i]); 
     168            all_ok=false; 
     169        } else { 
     170            //debugOutput(DEBUG_LEVEL_VERBOSE, "good result: %08X should be %08X\n", 
     171            //            buffer_1[i], buffer_ref[i]); 
     172        } 
     173    } 
     174 
     175    delete[] buffer_1; 
     176    delete[] buffer_ref; 
     177    return all_ok; 
     178} 
     179 
     180bool 
     181testFloatLabel(int nb_quadlets, int nb_tests) { 
     182    quadlet_t *buffer_1; 
     183    quadlet_t *buffer_ref; 
     184    quadlet_t *buffer_in; 
     185    float *buffer_float; 
     186    int i=0; 
     187     
     188    Util::SystemTimeSource time; 
     189    ffado_microsecs_t start; 
     190    ffado_microsecs_t elapsed; 
     191     
     192    setDebugLevel(DEBUG_LEVEL_MESSAGE); 
     193     
     194    buffer_1 = new quadlet_t[nb_quadlets]; 
     195    buffer_in = new quadlet_t[nb_quadlets]; 
     196    buffer_ref = new quadlet_t[nb_quadlets]; 
     197    buffer_float = new float[nb_quadlets]; 
     198     
     199    printMessage( "Generating test data...\n"); 
     200    for (i=0; i<nb_quadlets; i++) { 
     201        byte_t tmp = i & 0xFF; 
     202        buffer_in[i]   = tmp << 16; 
     203        tmp = (i + 1) & 0xFF; 
     204        buffer_in[i]   |= tmp << 8; 
     205        tmp = (i + 2) & 0xFF; 
     206        buffer_in[i]   |= tmp; 
     207         
     208        // convert to float and normalize 
     209        buffer_float[i] = (float)(buffer_in[i]); 
     210        buffer_float[i] /= (float)(0x007FFFFF); // range: 0..2 
     211        buffer_float[i] -= 1.0; // range: 1..-1 
     212         
     213        // copy to input buffer 
     214        float *t = &(buffer_float[i]); 
     215        quadlet_t *v = (quadlet_t *)t; 
     216        buffer_1[i] = *v; 
     217    } 
     218     
     219    // do reference conversion 
     220    for (i=0; i<nb_quadlets; i++) { 
     221        float v = (buffer_float[i]) * AMDTP_FLOAT_MULTIPLIER; 
     222        unsigned int tmp = ((int) v); 
     223        tmp = ( tmp >> 8 ) | 0x40000000; 
     224        buffer_ref[i] = tmp; 
     225    } 
     226     
     227    printMessage( "Performing AMDTP labeling...\n"); 
     228     
     229    int test=0; 
     230    for (test=0; test<nb_tests; test++) { 
     231    for (i=0; i<nb_quadlets; i++) { 
     232        // copy float to input buffer 
     233        float *t = &(buffer_float[i]); 
     234        quadlet_t *v = (quadlet_t *)t; 
     235        buffer_1[i] = *v; 
     236    } 
     237 
     238        start = time.getCurrentTimeAsUsecs(); 
     239        convertFromFloatAndLabelAsMBLA(buffer_1, nb_quadlets); 
     240        elapsed = time.getCurrentTimeAsUsecs() - start; 
     241        printMessage( " took %lluusec...\n", elapsed); 
     242    } 
     243 
     244    // check 
     245    printMessage( "Checking results...\n"); 
     246    bool all_ok=true; 
     247    for (i=0; i<nb_quadlets; i++) { 
     248        if (buffer_1[i] != buffer_ref[i]) { 
     249            printMessage( " bad result: %08X should be %08X\n", 
     250                        buffer_1[i], buffer_ref[i]); 
     251            all_ok=false; 
     252        } else { 
     253            //debugOutput(DEBUG_LEVEL_VERBOSE, "good result: %08X should be %08X\n", 
     254            //            buffer_1[i], buffer_ref[i]); 
     255        } 
     256    } 
     257 
     258    delete[] buffer_1; 
     259    delete[] buffer_ref; 
     260    delete[] buffer_in; 
     261    delete[] buffer_float; 
     262    return all_ok; 
     263} 
     264 
     265int 
     266main(int argc, char **argv) { 
     267 
     268    testByteSwap(NB_QUADLETS, NB_TESTS); 
     269    testInt24Label(NB_QUADLETS, NB_TESTS); 
     270    testFloatLabel(NB_QUADLETS, NB_TESTS); 
    118271     
    119272    return 0;