I'm working with managed and unmanaged code and I need to convert
convert array<uchar>^ image
to std::vector<char> data
.
I've started doing this:
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]);
}
It looks like it is working but it is very slow. Any idea about how can be done faster?
A first optimization you could do is to reserve the needed space in the vector, so it doesn't have to resize itself as you insert data into it.
This is as easy as:
data.reserve(tam);
This will improve performance, but not by that much. You can do better, you could use memcpy
, which, as cppreference says:
std::memcpy
is the fastest library routine for memory-to-memory copy.
So let's use that.
First, you need to resize (not reserve) the vector, so it knows the number of used bytes. Then, you can get a pointer to the raw data it holds with the data()
function.
As for the array, it's a managed object, which means you need to pin it so the GC won't move it around. In C++/CLI this is done with pin_ptr
.
Together, here's the final code:
data.resize(tam);
pin_ptr<uchar> pinned = &image[0];
std::memcpy(data.data(), pinned, tam);
I've tested it, and it's much faster. Here's a full test program:
#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;
}
My results are:
OP: 123 ms
reserve: 95 ms
memcpy: 8 ms