What is the fastest portable way to copy an array in C++

后端 未结 8 515
面向向阳花
面向向阳花 2020-12-30 02:11

This question has been bothering me for some time. The possibilities I am considering are

  1. memcpy
  2. std::copy
  3. cblas_dcopy

Does a

相关标签:
8条回答
  • 2020-12-30 02:45

    In most cases memcpy will be the fastest, as it is the lowest level and may be implemented in machine code on a given platform. (however, if your array contains non-trivial objects memcpy may not do the correct think, so it may be safer to stick with std::copy)

    However it all depends on how well the stdlib is implanted on the given platform etc. As the standard does not say how fast operations must be, there is no way to know in a “portable” since what will be fastest.

    Profiling your application will show the fasted on a given platform, but will only tell you about the test platform.

    However, when you profile you application you will most likely find that the issues are in your design rather than your choose of array copy method. (E.g. why do you need to copy large arrays so match?)

    0 讨论(0)
  • 2020-12-30 02:49

    I have to think that the others will call memcpy(). Having said that I can't beleive that there will be any appreciable difference.

    If it really matters to you, code all three and run a profiler, but it might be better to consider things like readability/maintainability, exception-safe, etc... (and code an assembler insert while you are at it, not that you are likely to see a difference)

    Is your program threaded?

    And, most importantly, how are you declating your array? (what is it an array of) and how large is it?

    0 讨论(0)
  • 2020-12-30 02:52

    In C++ you should use std::copy by default unless you have good reasons to do otherwise. The reason is that C++ classes define their own copy semantics via the copy constructor and copy assignment operator, and of the operations listed, only std::copy respects those conventions.

    memcpy() uses raw, byte-wise copy of data (though likely heavily optimized for cache line size, etc.), and ignores C++ copy semantics (it's a C function, after all...).

    cblas_dcopy() is a specialized function for use in linear algebra routines using double precision floating point values. It likely excels at that, but shouldn't be considered general purpose.

    If your data is "simple" POD type struct data or raw fundamental type data, memcpy will likely be as fast as you can get. Just as likely, std::copy will be optimized to use memcpy in these situations, so you'll never know the difference.

    In short, use std::copy().

    0 讨论(0)
  • 2020-12-30 02:52

    Use std::copy unless profiling shows you a needed benefit in doing otherwise. It honours the C++ object encapsulation, invoking copy constructors and assignment operators, and the implementation could include other inline optimisations. That's more maintainable if the types being copied are changed from something trivially copyable to something not.

    As PeterCordes comments below, modern compilers such as GCC and clang analyse memcpy() requests internally and typically avoid an out-of-line function call, and even before that some systems had memcpy() macros that inlined copies below a certain size threshold.

    FWIW / on the old Linux box I have handy (in 2010), GCC doesn't do any spectacular optimisations, but bits/type_traits.h does allow the program to easily specify whether std::copy should fall through to memcpy() (see code below), so there's no reason to avoid using std::copy() in favour of memcpy() directly.

     * Copyright (c) 1997
     * Silicon Graphics Computer Systems, Inc.
     *
     * Permission to use, copy, modify, distribute and sell this software
     * and its documentation for any purpose is hereby granted without fee,
     * provided that the above copyright notice appear in all copies and            
     * that both that copyright notice and this permission notice appear            
     * in supporting documentation.  Silicon Graphics makes no                      
     * representations about the suitability of this software for any               
     * purpose.  It is provided "as is" without express or implied warranty.        
     ...                                                                            
                                                                                
    /*                                                                              
    This header file provides a framework for allowing compile time dispatch        
    based on type attributes. This is useful when writing template code.            
    For example, when making a copy of an array of an unknown type, it helps        
    to know if the type has a trivial copy constructor or not, to help decide       
    if a memcpy can be used.
    
    The class template __type_traits provides a series of typedefs each of
    which is either __true_type or __false_type. The argument to
    __type_traits can be any type. The typedefs within this template will
    attain their correct values by one of these means:
        1. The general instantiation contain conservative values which work
           for all types.
        2. Specializations may be declared to make distinctions between types.
        3. Some compilers (such as the Silicon Graphics N32 and N64 compilers)
           will automatically provide the appropriate specializations for all
           types.
    
    EXAMPLE:
    
    //Copy an array of elements which have non-trivial copy constructors
    template <class _Tp> void
      copy(_Tp* __source,_Tp* __destination,int __n,__false_type);
    //Copy an array of elements which have trivial copy constructors. Use memcpy.
    template <class _Tp> void
      copy(_Tp* __source,_Tp* __destination,int __n,__true_type);
    
    //Copy an array of any type by using the most efficient copy mechanism
    template <class _Tp> inline void copy(_Tp* __source,_Tp* __destination,int __n) {
       copy(__source,__destination,__n,
            typename __type_traits<_Tp>::has_trivial_copy_constructor());
    }
    */
    
    0 讨论(0)
  • 2020-12-30 02:54

    memcpy, however, if your array contains non-trivial objects, stick with std::copy.

    0 讨论(0)
  • 2020-12-30 02:58

    I've made a small benchmark (VS 2018 Preview, MKL 2017 Update 4) to compare memcpy and the sequential version of cblas_?copy and found them to be equally fast on float and double.

    0 讨论(0)
提交回复
热议问题