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.

What is more efficient memcpy or loops?

I have several cases where an array of S16 values needs to be copied.  Usually memcpy would be the choice for large arrays.  However, the array size can vary (within the method) from 1 to 12 with most times being 2 values.  So my question, is it better to use memcpy and take the cost of a subroutine call or just do a loop, setting some pointers and running a for loop?

Right now, I'm using 3.3.67 CCS with 6.1.10 tools on a 6455 processor.  I should be upgrading to the latest CCS soon.  Also (as part of the upgrade) I will need to support the 6678 processor.

-- dave

  • To my experience the question is more complex that might seem on the first glance. Though I haven't seen memcpy()'s code, I can guess its internal structure. Roughly it consists of 3 stages. First, few initial elements are copied until memory pointer gets aligned on 64-bit boundary. Then bulk copy 8 bytes at a time stage takes place. Finally, tail part, if any unaligned present, is copied. So what behind that all? Efficiency of memcpy() is explained by bulk copy. In your custom program you have better knowledge on the nature of the array/memblock to copy, so you can do efficient copy as well. Suppose, you know that copies always happen in couples, i.e. 2, 4 or so 16-bit values. Then  you may take advantage of 32-bit copy instruction, _mem4(). Likewise, if you know that copies happen in fours, then you can use 64-bit copy instruction. Suppose, you know that copy always occurs at some nice boundary like 32 or bit. Then you may use instruction for aligned load. Again, this functionality already present in memcpy(), but has somewhat larger overhead to be universal.

    Another point of concern is code reuse. If such kind of copying happens in few places, no need to worry, but if there are a lot of occurrences, your app. may grow up.

    Now back closer to your case. With such small arrays function call overhead is comparable with job to do. Really, you'll have to pass 2 pointers and element count. These are 3 integer copies to stack. At least you have to copy return address to stack - one more integer. 4 integers are 8 S16, so copying them manually might be same efficient.

    And, finally, if you want to squeeze every single bit of your DSP performance, then some more work may help. If you experiment with o3 optimization level and set fixed element count, you may see that compiler will unroll your loops. Literally, there will be no loop in assembly. So, you may check, whether element count is even and apply 32-bit copy. You don't need to type intrinsic instruction yourself, just place proper pragma and compiler will do the job. Something like this:

     

    if (count & 0x1) // odd element count

        for (i = 0; i < count; i++) *dst++ = *src++;

    else // even element count

    {

        #pragma MUST_ITERATE( , , 2)

        for (i = 0; i < count; i++) *dst++ = *src++;

    }

    Else branch will get unrolled.

    Please don't accept these consideration as direct manual, I'd like to give you just some insight, what happens behind.