Лучший способ скопировать несколько std :: vectors в 1? (Многопоточный) - PullRequest
3 голосов
/ 07 июля 2010

Вот что я делаю:

Я беру точки Безье и запускаю интерполяцию Безье, а затем сохраняю результат в std::vector<std::vector<POINT>.

Подсчет Безье замедлил меня, поэтому я и сделал это.

Я начинаю с std::vector<USERPOINT>, который является структурой с точкой и двумя другими точками для ручек Безье.

Я делю их на ~ 4 группы и назначаю каждый поток для выполнения 1/4 работы. Для этого я создал 4 std::vector<std::vector<POINT> > для хранения результатов из каждого потока. В конце все точки должны быть в 1 непрерывном векторе, прежде чем я использовал многопоточность, я получил к нему прямой доступ, но теперь я оставляю за собой размер 4 векторов по нитям и вставьте их в исходный вектор, в правильном порядке. Это работает, но, к сожалению, часть копирования очень медленная и делает ее медленнее, чем без многопоточности. Так что теперь мое новое узкое место копирует результаты в вектор. Как я могу сделать это более эффективно?

Спасибо

Ответы [ 3 ]

4 голосов
/ 07 июля 2010

Сделайте так, чтобы все потоки помещали свои результаты в один непрерывный вектор, как и раньше.Вы должны убедиться, что каждый поток обращается только к тем частям вектора, которые отделены от других.Пока это так (что должно быть независимо - вы не хотите генерировать один и тот же вывод дважды), каждый по-прежнему работает с памятью, отделенной от других, и вам не нужна блокировка (и т. Д.)чтобы вещи работали.Однако вам необходимо / нужно убедиться, что вектор для результата имеет правильный размер для всех результатов первым - несколько потоков пытаются (например) вызвать resize() или push_back() для вектора . посеять хаос в спешке (не говоря уже о том, чтобы вызвать копирование, которого вы явно хотите здесь избежать).

Редактировать: Как отметил Билли О'Нил, обычный способ сделать это - пройтиуказатель на каждую часть вектора, где каждый поток будет размещать свой вывод.Ради аргумента давайте предположим, что мы используем std::vector<std::vector<POINT> >, упомянутый в качестве оригинальной версии вещей.На данный момент я собираюсь пропустить детали создания потоков (тем более, что это зависит от системы).Для простоты я также предполагаю, что количество генерируемых кривых является точным кратным числу потоков - в действительности, кривые не будут делиться точно равномерно, поэтому вам придется «выдумать»рассчитывать на одну нить, но это на самом деле не имеет отношения к рассматриваемому вопросу.

std::vector<USERPOINT> inputs; // input data   
std::vector<std::vector<POINT> > outputs; // space for output data

const int thread_count = 4;

struct work_packet {           // describe the work for one thread
    USERPOINT *inputs;         // where to get its input
    std::vector<POINT> *outputs;   // where to put its output
    int num_points;                // how many points to process
    HANDLE finished;               // signal when it's done.
};

std::vector<work_packet> packets(thread_count); // storage for the packets.
std::vector<HANDLE> events(thread_count);       // storage for parent's handle to events

outputs.resize(inputs.size);                    // can't resize output after processing starts.

for (int i=0; i<thread_count; i++) {
    int offset = i * inputs.size() / thread_count;
    packets[i].inputs = &inputs[0]+offset;
    packets[i].outputs = &outputs[0]+offset;
    packets[i].count = inputs.size()/thread_count;
    events[i] = packets[i].done = CreateEvent();

    threads[i].process(&packets[i]);
}


// wait for curves to be generated (Win32 style, for the moment).
WaitForMultipleObjects(&events[0], thread_count, WAIT_ALL, INFINITE);

Обратите внимание, что хотя мы должны быть уверены, что вектор outputs не будет изменен при работе с несколькими потокамиотдельные векторы точек в выходах могут быть, потому что каждый из них когда-либо будет затронут только одним потоком за раз.

0 голосов
/ 07 июля 2010

Если простое копирование между вещами происходит медленнее, чем до того, как вы начали использовать многозадачность, вполне вероятно, что то, что вы делаете простым, не будет масштабироваться до нескольких ядер.Если это что-то простое, например, что-то вроде Безье, я подозреваю, что так оно и будет.

Помните, что накладные расходы на создание потоков и тому подобное влияют на общее время выполнения.

Наконец ... длякопия, что вы используете?Это std::copy?

0 голосов
/ 07 июля 2010

Многопоточность не ускорит ваш процесс. Обработка данных в разных ядрах, может.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...