Преобразовать массив<uchar>^ в данные std::vector<char>;
Я работаю с управляемым и неуправляемым кодом, и мне нужно конвертировать конвертировать 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]);
}
Похоже, это работает, но это очень медленно. Любая идея о том, как можно сделать быстрее?
1 ответ
Первая оптимизация, которую вы можете сделать, это зарезервировать необходимое пространство в векторе, чтобы он не изменял свой размер при вставке в него данных.
Это так же просто, как:
data.reserve(tam);
Это улучшит производительность, но не намного. Вы можете сделать лучше, вы могли бы использовать memcpy
, который, как говорит cppreference:
std::memcpy
является самой быстрой библиотечной подпрограммой для копирования из памяти в память.
Итак, давайте использовать это.
Во-первых, вам нужно изменить размер (не зарезервировать) вектор, чтобы он знал количество используемых байтов. Затем вы можете получить указатель на необработанные данные, которые он содержит с data()
функция.
Что касается массива, то это управляемый объект, что означает, что вам нужно закрепить его, чтобы 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