我正在使用托管和非托管代码,我需要转换
将array<uchar>^ image
转换为std::vector<char> data
。
我开始这样做了:
array<uchar> ^image = gcnew array<uchar>(tam);
reader2->GetBytes(0, 0, image, 0, tam);
vector<uchar> data;
for (int idxImage = 0; idxImage < tam; idxImage++)
{
data.push_back(image[idxImage]);
}
它看起来很有效,但速度很慢。关于如何更快地完成任何想法?
答案 0 :(得分:2)
您可以做的第一个优化是保留向量中所需的空间,因此在向其中插入数据时不必自行调整大小。
这很简单:
data.reserve(tam);
这将提高性能,但不会那么多。你可以做得更好,你可以使用memcpy
,cppreference says:
std::memcpy
是内存到内存复制的最快库例程。
所以让我们使用它。
首先,您需要调整(不是保留)向量,因此它知道使用的字节数。然后,您可以使用data()
函数获取指向它所保存的原始数据的指针。
对于数组,它是一个托管对象,这意味着你需要 pin 它,所以GC不会移动它。在C ++ / CLI中,这是通过pin_ptr
完成的。
总之,这是最终的代码:
data.resize(tam);
pin_ptr<uchar> pinned = &image[0];
std::memcpy(data.data(), pinned, tam);
我已经对它进行了测试,而且很多更快。这是一个完整的测试程序:
#include "stdafx.h"
#include <vector>
typedef unsigned char uchar;
void test1(array<uchar>^ image)
{
std::vector<uchar> data;
int tam = image->Length;
auto sw = System::Diagnostics::Stopwatch::StartNew();
for (int idxImage = 0; idxImage < tam; idxImage++)
{
data.push_back(image[idxImage]);
}
sw->Stop();
System::Console::WriteLine("OP: {0} ms", sw->ElapsedMilliseconds);
}
void test2(array<uchar>^ image)
{
std::vector<uchar> data;
int tam = image->Length;
auto sw = System::Diagnostics::Stopwatch::StartNew();
data.reserve(tam);
for (int idxImage = 0; idxImage < tam; idxImage++)
{
data.push_back(image[idxImage]);
}
sw->Stop();
System::Console::WriteLine("reserve: {0} ms", sw->ElapsedMilliseconds);
}
void test3(array<uchar>^ image)
{
std::vector<uchar> data;
int tam = image->Length;
auto sw = System::Diagnostics::Stopwatch::StartNew();
data.resize(tam);
pin_ptr<uchar> pinned = &image[0];
std::memcpy(data.data(), pinned, tam);
sw->Stop();
System::Console::WriteLine("memcpy: {0} ms", sw->ElapsedMilliseconds);
}
int main(array<System::String ^> ^args)
{
size_t tam = 20 * 1024 * 1024;
array<uchar>^ image = gcnew array<uchar>(tam);
(gcnew System::Random)->NextBytes(image);
test1(image);
test2(image);
test3(image);
return 0;
}
我的结果是:
OP: 123 ms
reserve: 95 ms
memcpy: 8 ms