【问题标题】:Most efficient way of copying a raw byte array into an empty byte vector将原始字节数组复制到空字节向量中的最有效方法
【发布时间】:2016-01-01 00:53:08
【问题描述】:

我有一个场景,我需要将原始动态分配的uint8_t 数组的内容复制到一个向量中(保证在这种情况发生时为)。

vector<uint8_t> myVector;
const uint8_t* myRawArray;

复制操作尽可能高效且可移植(可能使用各种编译器版本)对我来说非常重要。

我想到的一种方法是:

myVector.reserve(byteCount);
myVector.insert(myVector.begin(), myRawArray, myRawArray + byteCount);

关于它的速度与这个相比如何的任何想法:

myVector.resize(byteCount);
memcpy(myVector.data(), myRawArray, byteCount);

我猜memcpy 应该很快,但后来我不得不使用resize,它需要将内存清零,所以我想它会减慢一点..

另外,还有什么建议吗?

【问题讨论】:

  • 测量呢?
  • 我见过这个问题的几个微妙不同的版本。无论哪种方式都没有太多性能,最快的解决方案因编译器和硬件而异。我可能只是使用插入版本作为其最惯用的 C++。如果我们有特定的硬件和编译器作为目标,那么继续进行测量
  • 另一个选项是:myVector.reserve(byteCount); std::copy(myRawArray, myRawArray + byteCount, std::back_inserter(myVector));
  • 你的想法是理智的。测量它们以找出在目标平台上哪一个对您的数据最快。 (但我预计通常接近 nil 差异。)
  • 另一种选择,如果可以在复制时声明向量:std::vector&lt;uint8_t&gt; myVector(myRawArray, myRawArray + byteCount); 否则,swap() 临时向量:std::vector&lt;uint8_t&gt; tmp(myRawArray, myRawArray + byteCount); myVector.swap(tmp);

标签: c++ vector stl


【解决方案1】:

如果您不需要在复制之前创建向量,您可以随时将原始数组传递给向量的构造函数:

std::vector<uint8_t> myVector(myRawArray, myRawArray + byteCount);

如果确实需要事先构造向量,可以选择以下方式:

std::vector<uint8_t> myVector;
// ... do some stuff ...
// Now, we're ready for the copy, and byteCount is known.
myVector.reserve(byteCount);
std::copy(myRawArray, myRawArray + byteCount, std::back_inserter(myVector));

我建议使用 std::copy 除非 memcpy 被证明更快。 std::copy 在 C++ 代码中更安全、更惯用,但如果确实证明它更快,请不要害怕使用 memcpy。速度差异很可能会随着不同的编译器而变化。

我希望这会有所帮助。

【讨论】:

  • @M.M:我不知道 std::vector 的范围构造函数将向量的元素初始化为零。这背后的原理是什么?
【解决方案2】:

memcpy() 通常是用汇编语言编写的,并且经过了非常优化,所以你应该知道memcpy 会很快。 vector::insert 通常实现为在后台调用memcpy,但它确实需要检查向量中是否有足够的空间来进行插入而不进行任何重新分配。我没有对此进行分析,但我敢打赌调用reserve 的第一个版本更快。

另一种方法是使用std::copy,在某些情况下,它被发现比使用memcpy 稍快,您可以确定如果可能的话,它还会调用memcpy 或执行某些操作更好的。所以性能问题不应该是它的问题。它还将负责增加向量的大小以满足您的要求。

【讨论】:

    【解决方案3】:

    感谢大家对我的问题的意见我已经通过对我的结构进行以下更改并像这样实现它来解决问题

       struct YUV_Buffer
       {
    void *pCacheBuf = nullptr;
    int frameID = 0;
    int height = 0;
    int width = 0;
    void CopyBuf(BYTE * pBuf, int sizBuf)
    {
        pCacheBuf = new BYTE[sizBuf];
        memcpy(pCacheBuf, pBuf, sizBuf);
    }
    
    YUV_Buffer(BYTE * pBuf, int nFrameID, int nHeight, int nWidth)
        : frameID(nFrameID), height(nHeight), width(nWidth)
    {
        CopyBuf(pBuf, 8 * 1024 * 1024);
    }
    
    YUV_Buffer(const YUV_Buffer & yuvbuf)
        :frameID(yuvbuf.frameID), height(yuvbuf.height), width(yuvbuf.width)
    {
        CopyBuf((BYTE*)yuvbuf.pCacheBuf, 8 * 1024 * 1024);
    }
    ~YUV_Buffer() {
        delete[]pCacheBuf;
        pCacheBuf = NULL;
    }
     };
    

    然后我像这样实现它:

      YUV_Buffer nBuffer = YUV_Buffer((BYTE*)pSysFrame, pmfxInSurface->Data.FrameOrder, pmfxInSurface->Info.CropH, pmfxInSurface->Info.CropW);
    mBuffer.emplace_back(nBuffer);
    

    希望这可以帮助其他人,也可以从专家交流中补充 sarabande,以获得帮助和意见。

    问候 奈杰尔

    【讨论】:

      猜你喜欢
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 2019-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-25
      • 2021-09-13
      相关资源
      最近更新 更多