Преобразовать массив<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
Другие вопросы по тегам