RF>Этот процесс копирования занимает 20 секунд.
RF>Можно ли как-то сделать это копирование быстрее? Какой код для этого следует использовать?
Можно. Для этого нужно использовать такой код:
measurevector2 = measurevector;
Следующим шагом можно подумать, а действительно ли здесь необходимо копирование. Если окажется, что вместо копирования подходит перемещение, то время сведется вообще к нулю.
--
Не можешь достичь желаемого — пожелай достигнутого.
Есть некоторая структура Measure_Simulation, которая включает в себя достаточно много полей типа int, long, long double, char*, bool.
И есть вектор (std::vector) measuresvector, каждый элемент которого относится к типу Measure_Simulation. Этот вектор имеет 40 тысяч таких элементов.
Я копирую содержимое вектора measuresvector в другой вектор measuresvector2, используя следующий код:
Здравствуйте, RussianFellow, Вы писали:
RF>Можно ли как-то сделать это копирование быстрее? Какой код для этого следует использовать?
зарезервировать 40 тыс. элементов — при помощи метода my_vector.reserve(40000);
UPD:
measuresvector2.reserve(measuresvector.size()); // Резервируем под вектор необходимый размер
std::back_insert_iterator<std::vector <Measure_Simulation> > toV(measuresvector2);
std::copy(measuresvector.begin(),measuresvector.end(),toV);
RF>Можно ли изменить этот код, чтобы он работал быстрее? Что для этого нужно сделать?
Зачем понадобилось два вектора? Напиши логику работы с ними.
Может быть вместо этого хранить всё в одном векторе и сделать обёртку, которая будет обращаться к нужному участку вектора? Или сделать список векторов.
Здравствуйте, RussianFellow, Вы писали:
RF>Есть некоторая структура Measure_Simulation, которая включает в себя достаточно много полей типа int, long, long double, char*, bool.
слешка настораживают типы char*
RF>И есть вектор (std::vector) measuresvector, каждый элемент которого относится к типу Measure_Simulation. Этот вектор имеет 40 тысяч таких элементов.
RF>Я копирую содержимое вектора measuresvector в другой вектор measuresvector2, используя следующий код:
данная структура имеет свой оператор копирования или по умолчанию просто копирует все поля как быйты?
RF>
RF>Этот процесс копирования занимает 20 секунд.
RF>Можно ли как-то сделать это копирование быстрее?
А чему равно sizeof(Measure_Simulation)*40000шт/20сек = ?
Если это < 40Gb/sec то можно ускорять. RF>Какой код для этого следует использовать?
memcpy
S>>Ну, вам нужно ещё многому учиться. Сейчас std::copy() принимает пару итераторов и range в std::ranges::copy(). Причём здесь инвалидация при переаллокации, если не происходит копирование контейнера самого в себя, я не знаю. R>Безуспешно пытаюсь найти описанную тобой версию copy. Я уточню, ты точно знаешь, что такая версия будет, или предполагаешь, что такое такое теоретически возможно?
Да не ищи, нет такой.
"For every complex problem, there is a solution that is simple, neat,
and wrong."
Здравствуйте, Nuzhny, Вы писали:
N>#pragma omp parallel for
Тут особо выигрыша не будет. Так как здесь не CPU узкое место, а пропускная способность памяти (RAM).
В память может и упрется.
Здравствуйте, RussianFellow, Вы писали:
RF>А зачем нужно резервирование элементов?
Чтобы во время копирования не резервировалась память и не выполнялось копирование "под капотом"
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, RussianFellow, Вы писали:
RF>А зачем нужно резервирование элементов?
Все реализации вектора должны хранить свои элементы последовательно в памяти.
Условно говоря, изначально вектор в конструкторе выделяет память на N элементов, где N — небольшое число (обычно 8-16 элементов).
После заполнения этой памяти, вектор выделяет память в два раза больше (или всего лишь на 10% больше) и копирует туда элементы из старого массива в новый.
Старый массив удаляет. Когда у тебя 40 тыс. элементов добавятся таких реаллокаций будет множество — из-за них и тормозит.
Это такой std::vector. Из-за требования хранить все элементы рядом друг с другом. std::list от такого недостатка свободен, но у него есть накладные расходы по памяти.
Здравствуйте, GhostCoders, Вы писали:
GC>Здравствуйте, Nuzhny, Вы писали:
N>>#pragma omp parallel for GC>Тут особо выигрыша не будет. Так как здесь не CPU узкое место, а пропускная способность памяти (RAM). GC>В память может и упрется.
Ещё взглянуть бы на конструктор копии Measure_Simulation, может быть он тоже медленный. По описанию "много полей типа int, long, long double, char*, bool") сильно тормозить не должен, но вдруг там гигабайты этих полей.
Здравствуйте, GhostCoders, Вы писали:
GC>зарезервировать 40 тыс. элементов — при помощи метода my_vector.reserve(40000);
GC>
GC>measuresvector2.reserve(measuresvector.size()); // Резервируем под вектор необходимый размер
GC>std::back_insert_iterator<std::vector <Measure_Simulation> > toV(measuresvector2);
GC>std::copy(measuresvector.begin(),measuresvector.end(),toV);
GC>
Разве copy не сделает этого автоматически? Это же интервальная функция, она должна понимать размер коипируемого. По идее, трейты в шаблонах вполне позволяют понять тип итератора, вычислить длину и зарезервить.
Проект Ребенок8020 — пошаговый гайд как сделать, вырастить и воспитать ребенка.
Ну, вам нужно ещё многому учиться. Сейчас std::copy() принимает пару итераторов и range в std::ranges::copy(). Причём здесь инвалидация при переаллокации, если не происходит копирование контейнера самого в себя, я не знаю.
Здравствуйте, rg45, Вы писали:
R>Как, имея один только простой указатель, алгоритм copy может прийти к выводу, что это этот указатель — итератор вектора? А потом найти этот вектор и модифицировать его. Расскажешь?
R>P.S. И как быть с инвалидацией итераторов при переаллокации — это будет следующий вопрос.
Ну, скажем, в майкрософтовской STL (да и в других, наверное) есть специализация std::copy() для POD типов, где сразу вызывается std::memcpy(), так что я не вижу причин, чтобы не было оптимизации для рэнджей с известным размером и последовательно расположенными элементами.
Здравствуйте, rg45, Вы писали:
R>Безуспешно пытаюсь найти описанную тобой версию copy. Я уточню, ты точно знаешь, что такая версия будет, или предполагаешь, что такое такое теоретически возможно?
Здравствуйте, RussianFellow, Вы писали:
RF>И ещё вопрос: как лучше всего добавить содержимое вектора measuresvector в конец вектора measuresvector2 ? RF>Есть код:
RF>
Здравствуйте, AleksandrN, Вы писали:
R>>Копирование std::vector глазами разработчика _обычного_ языка программирования: R>>Img.
AN>Чем обычный язык программирования отличается от необычного?
Таки нашелся тот, кто заставил объяснять шутку. Ну, допустим, НЕ обычный — это C++. Соответственно, любой язык, отличный от С++ — обычный. Как тебе такая версия?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, GhostCoders, Вы писали:
N>>#pragma omp parallel for GC>Тут особо выигрыша не будет. Так как здесь не CPU узкое место, а пропускная способность памяти (RAM). GC>В память может и упрется.
Набросал тест с POD структурой на своём 6-ядерном ноуте и параллельная версия получилась процентов на 10 быстрее. Согласен, что на маленьких данных выигрыша особого не будет. Но на больших объёмах он вполне возможен, почему нет? Особенно если много памяти занимает и она многоканальная.
Здравствуйте, Nuzhny, Вы писали:
N>Набросал тест с POD структурой на своём 6-ядерном ноуте и параллельная версия получилась процентов на 10 быстрее. Согласен, что на маленьких данных выигрыша особого не будет. Но на больших объёмах он вполне возможен, почему нет? Особенно если много памяти занимает и она многоканальная.
10 процентов єто как раз "особого віигріша не будет"
Здравствуйте, rg45, Вы писали:
R>Таки нашелся тот, кто заставил объяснять шутку. Ну, допустим, НЕ обычный — это C++. Соответственно, любой язык, отличный от С++ — обычный. Как тебе такая версия?
В єтой ветке ожидается 200+ сообщений.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, AleksandrN, Вы писали:
R>>>Копирование std::vector глазами разработчика _обычного_ языка программирования: R>>>Img.
AN>>Чем обычный язык программирования отличается от необычного?
R>Таки нашелся тот, кто заставил объяснять шутку. Ну, допустим, НЕ обычный — это C++. Соответственно, любой язык, отличный от С++ — обычный. Как тебе такая версия?
Тогда прыгун должен прыгать в чёрном полупрозрачном ящике. Степень прозрачности зависит от необычности языка. Чем необычней тем прозрачней.
Здравствуйте, AleksandrN, Вы писали:
AN>Тогда прыгун должен прыгать в чёрном полупрозрачном ящике. Степень прозрачности зависит от необычности языка. Чем необычней тем прозрачней.
Слишком сложная шутка. Для меня это некст левел.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, AleksandrN, Вы писали:
AN>>Тогда прыгун должен прыгать в чёрном полупрозрачном ящике. Степень прозрачности зависит от необычности языка. Чем необычней тем прозрачней.
R>Слишком сложная шутка. Для меня это некст левел.
Значит показано копирование std::vector глазами разработчика на ассемблере или Си. Для них всё прозрачно и кажется излишними выкрутасами
Здравствуйте, RussianFellow, Вы писали:
RF>Можно ли как-то сделать это копирование быстрее? Какой код для этого следует использовать?
Да.
Сделать Measure_Simulation implicitly shared class-ом (копирование при неконстантном доступе).
По сути, это pimpl + подсчет ссылок на атомиках (если код не многопоточный, то можно и не на атомиках).
Или использовать shared_ptr, если нужно совместное владение.
Или использовать unique_ptr, если не нужно.
Или использовать что-то типа QSharedDataPointer, boost::intrusive_ptr.
Здравствуйте, Basil2, Вы писали:
B>Разве copy не сделает этого автоматически? Это же интервальная функция, она должна понимать размер коипируемого. По идее, трейты в шаблонах вполне позволяют понять тип итератора, вычислить длину и зарезервить.
Хороший вопрос. Но, как говорится, доверяй, но проверяй.
Здравствуйте, Basil2, Вы писали:
B>Разве copy не сделает этого автоматически? Это же интервальная функция, она должна понимать размер коипируемого. По идее, трейты в шаблонах вполне позволяют понять тип итератора, вычислить длину и зарезервить.
Нет конечно. Copy занимается только копированием, такова семантика алгоритма. И в качестве назначения копирования ему передается не весь контейнер, а только итератор (который может оказаться простым указателем). И о том, чтобы этот итератор не вышел за дозволенные пределы, должна позаботиться вызывающая функция.
--
Не можешь достичь желаемого — пожелай достигнутого.
С range'ами и концептами, наверное, будет так. Потому как появился концепт SizedRange.
Здравствуйте, rg45, Вы писали:
R>Нет конечно. Copy занимается только копированием, такова семантика алгоритма. И в качестве назначения копирования ему передается не весь контейнер, а только итератор (который может оказаться простым указателем). И о том, чтобы этот итератор не вышел за дозволенные пределы, должна позаботиться вызывающая функция.
Здравствуйте, swingus, Вы писали:
R>>Нет конечно. Copy занимается только копированием, такова семантика алгоритма. И в качестве назначения копирования ему передается не весь контейнер, а только итератор (который может оказаться простым указателем). И о том, чтобы этот итератор не вышел за дозволенные пределы, должна позаботиться вызывающая функция.
S>С range'ами и концептами, наверное, будет так. Потому как появился концепт SizedRange.
Как, имея один только простой указатель, алгоритм copy может прийти к выводу, что это этот указатель — итератор вектора? А потом найти этот вектор и модифицировать его. Расскажешь?
P.S. И как быть с инвалидацией итераторов при переаллокации — это будет следующий вопрос.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, swingus, Вы писали:
S>Ну, вам нужно ещё многому учиться. Сейчас std::copy() принимает пару итераторов и range в std::ranges::copy(). Причём здесь инвалидация при переаллокации, если не происходит копирование контейнера самого в себя, я не знаю.
Ну так с этого и надо было начинать. Сылочку можно?
Здравствуйте, swingus, Вы писали:
S>Ну, вам нужно ещё многому учиться. Сейчас std::copy() принимает пару итераторов и range в std::ranges::copy(). Причём здесь инвалидация при переаллокации, если не происходит копирование контейнера самого в себя, я не знаю.
Безуспешно пытаюсь найти описанную тобой версию copy. Я уточню, ты точно знаешь, что такая версия будет, или предполагаешь, что такое такое теоретически возможно?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, AndrewJD, Вы писали:
S>>>Ну, вам нужно ещё многому учиться. Сейчас std::copy() принимает пару итераторов и range в std::ranges::copy(). Причём здесь инвалидация при переаллокации, если не происходит копирование контейнера самого в себя, я не знаю.
R>>Безуспешно пытаюсь найти описанную тобой версию copy. Я уточню, ты точно знаешь, что такая версия будет, или предполагаешь, что такое такое теоретически возможно?
AJD>Да не ищи, нет такой.
Ну вот, а я только настроился _многому_научиться_
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, swingus, Вы писали:
R>>Безуспешно пытаюсь найти описанную тобой версию copy. Я уточню, ты точно знаешь, что такая версия будет, или предполагаешь, что такое такое теоретически возможно?
S>Ну, скажем, в майкрософтовской STL (да и в других, наверное) есть специализация std::copy() для POD типов, где сразу вызывается std::memcpy(), так что я не вижу причин, чтобы не было оптимизации для рэнджей с известным размером и последовательно расположенными элементами.
Это принципиально разные задачи. Для оптимизации копирования POD-типов доступ к контейнеру не требуется. А для изменения размера контейнера требуется доступ к этому контейнеру. А для этого должна существовать версия функции, которая принимает range (именно range, а не итератор). А где эта функция, она сущетвует в природе? В этом же был вопрос.
Я еще на всякий случай хочу уточнить, ты понимаешь, что НА ИМЕЮЩИХСЯ вариантах задача изменения размера контейнера во время копирования не решаема? Или не понимаешь?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, GhostCoders, Вы писали:
N>>Набросал тест с POD структурой на своём 6-ядерном ноуте и параллельная версия получилась процентов на 10 быстрее. Согласен, что на маленьких данных выигрыша особого не будет. Но на больших объёмах он вполне возможен, почему нет? Особенно если много памяти занимает и она многоканальная. GC>10 процентов єто как раз "особого віигріша не будет"
Переехал таки в Полтаву? Или на родине завел себе клавиатуру без "ы", но с "є"
Ну, возможно, тебе приходило такое в голову, что ranges-v3 оперирует рэнжами? И, может быть, ты слышал, что её включили в C++ 20?
Здравствуйте, rg45, Вы писали:
R>Это принципиально разные задачи. Для оптимизации копирования POD-типов доступ к контейнеру не требуется. А для изменения размера контейнера требуется доступ к этому контейнеру. А для этого должна существовать версия функции, которая принимает range (именно range, а не итератор). А где эта функция, она сущетвует в природе? В этом же был вопрос.
R>Я еще на всякий случай хочу уточнить, ты понимаешь, что НА ИМЕЮЩИХСЯ вариантах задача изменения размера контейнера во время копирования не решаема? Или не понимаешь?
Здравствуйте, RussianFellow, Вы писали:
RF>Есть некоторая структура Measure_Simulation, которая включает в себя достаточно много полей типа int, long, long double, char*, bool. RF>И есть вектор (std::vector) measuresvector, каждый элемент которого относится к типу Measure_Simulation. Этот вектор имеет 40 тысяч таких элементов. RF>Я копирую содержимое вектора measuresvector в другой вектор measuresvector2, используя следующий код:
RF>
Здравствуйте, swingus, Вы писали:
S>Ну, возможно, тебе приходило такое в голову, что ranges-v3 оперирует рэнжами? И, может быть, ты слышал, что её включили в C++ 20?
Вообще, мне много всего приходило и продолжает приходить в голову. Но почему бы тебе просто не ответить на вопрос
Да, алгоритмов, принимающих контейнер, в ranges v3 нет. Я был неправ. Единственное, что меня частично извиняет, это то, что в boost.ranges v2 такие алгоритмы есть — push_back(), push_front() & insert().
Здравствуйте, rg45, Вы писали:
R>Вообще, мне много всего приходило и продолжает приходить в голову. Но почему бы тебе просто не ответить на вопрос