std::vector insert
От: ahaos  
Дата: 08.09.19 08:30
Оценка:
В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.

Делается это так.
res.insert(res.end(), a.begin(), a.end()); (исправлено)

При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех.
Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще. Сортировка массивов res, a не допустима.
Отредактировано 08.09.2019 13:52 ahaos . Предыдущая версия .
Re: std::vector insert
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 08.09.19 08:34
Оценка:
Здравствуйте, ahaos, Вы писали:

A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.


A>Делается это так.

A>res.insert(res.begin(), a.begin(), a.end());

A>При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех.

A>Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще. Сортировка массивов res, a не допустима.

Могу предположить, что идет постоянное перераспределение памяти. Можно попробовать навскидку оценить размер финального вектора, и зарезервировать нужное количество элементов
Маньяк Робокряк колесит по городу
Re: std::vector insert
От: watchmaker  
Дата: 08.09.19 09:00
Оценка: +1
Здравствуйте, ahaos, Вы писали:

A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.

Так к концу или к началу?
Потому как в твоём коде новый массив добавляется именно в начало. А для std::vector это дорогая операция.
A>Делается это так.
A>res.insert(res.begin(), a.begin(), a.end());

A>При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех.


A>Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще.

Для вставки в начало лучше либо взять другой контейнер (например, дек), либо вставлять в вектор всё равно в конец элементы в обратном порядке, а потом в самом конце применить однократно std::reverse.

Если вставлять нужно всё же в конец, то лучше будет, как уже сказали, попробовать угадать размер и сделать однократный reserve. Ну и часто лучше вообще не формировать временные вектора, а попробовать переписать код так, чтобы он умел работать с res непосредственно.
Re: std::vector insert
От: kov_serg Россия  
Дата: 08.09.19 10:08
Оценка: +2
Здравствуйте, ahaos, Вы писали:

A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.


A>Делается это так.

A>res.insert(res.begin(), a.begin(), a.end());
Не к тому концу вы добавляете элементы.

A>При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех.

Не удивительно.

A>Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще. Сортировка массивов res, a не допустима.

res.insert(res.end(), a.begin(), a.end());
Re: std::vector insert
От: LaptevVV Россия  
Дата: 08.09.19 13:42
Оценка:
A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.
Отсортированный или нет?
A>Делается это так.
A>res.insert(res.begin(), a.begin(), a.end());
Добавляешь в начало.
Может так пойдет: ?
1. Поэлементно добавляешь в конец вектора операцией pus_back()
2. Поэлементно обмениваешь с первыми элементами вектора
При большом размере вектора перераспределение памяти делается редко.
Как правило, в конце вектора память уже выделена.
Так что отследи только, что с чем в каком порядке менять из конца в начало.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: std::vector insert
От: ahaos  
Дата: 08.09.19 13:54
Оценка:
Здравствуйте, LaptevVV, Вы писали:

A>>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.

LVV>Отсортированный или нет?
A>>Делается это так.
A>>res.insert(res.begin(), a.begin(), a.end());
LVV>Добавляешь в начало.
LVV>Может так пойдет: ?
LVV>1. Поэлементно добавляешь в конец вектора операцией pus_back()
LVV>2. Поэлементно обмениваешь с первыми элементами вектора
LVV>При большом размере вектора перераспределение памяти делается редко.
LVV>Как правило, в конце вектора память уже выделена.
LVV>Так что отследи только, что с чем в каком порядке менять из конца в начало.


Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение.
Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять
Re[3]: std::vector insert
От: LaptevVV Россия  
Дата: 08.09.19 13:58
Оценка:
A>Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение.
A>Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять
Дело в том, что при выполнении операции push_back() вектор при нехватке памяти сам выделяет новое место.
И выделяет не по 1 элементу, а сразу столько же, сколько в векторе имеется.
Поэтому с увеличением вектора новая память выделяется все реже.
Но если хотя бы примерно известен наибольший размер, то да, лучше заранее выделить столько 1 раз, и уже не париться.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: std::vector insert
От: Stanislav V. Zudin Россия  
Дата: 08.09.19 16:49
Оценка: +1
Здравствуйте, LaptevVV, Вы писали:

LVV>Может так пойдет: ?

LVV>1. Поэлементно добавляешь в конец вектора операцией pus_back()
LVV>2. Поэлементно обмениваешь с первыми элементами вектора

3. Заменить std::vector на std::deque? Если нужна вставка непременно в начало.
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: std::vector insert
От: LaptevVV Россия  
Дата: 08.09.19 16:58
Оценка:
SVZ>3. Заменить std::vector на std::deque? Если нужна вставка непременно в начало.
Это да. Только не в студийной реализации — там дек реализован очень плохо.
В gcc — все гораздо лучше.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: std::vector insert
От: Stanislav V. Zudin Россия  
Дата: 08.09.19 17:17
Оценка:
Здравствуйте, LaptevVV, Вы писали:

SVZ>>3. Заменить std::vector на std::deque? Если нужна вставка непременно в начало.

LVV>Это да. Только не в студийной реализации — там дек реализован очень плохо.

А чего там накосячили?
В код заглянул — без поллитры не разобрать. Где подвоха ждать?

LVV>В gcc — все гораздо лучше.


Увы, нам не актуально.
_____________________
С уважением,
Stanislav V. Zudin
Re[3]: std::vector insert
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 08.09.19 18:47
Оценка: +1
Здравствуйте, ahaos, Вы писали:

A>Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение.

A>Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять

Надо не выделять — не задавать размер вектора, а резервировать — методом reserve, а потом добавлять, как и делал раньше
Маньяк Робокряк колесит по городу
Re[4]: std::vector insert
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 08.09.19 18:48
Оценка:
Здравствуйте, LaptevVV, Вы писали:

A>>Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение.

A>>Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять
LVV>Дело в том, что при выполнении операции push_back() вектор при нехватке памяти сам выделяет новое место.
LVV>И выделяет не по 1 элементу, а сразу столько же, сколько в векторе имеется.

Это не так. Насколько я знаю, большинство реализаций использует кэф 1.2 где-то. Он был признан оптимальным на все случаи жизни
Маньяк Робокряк колесит по городу
Re[5]: std::vector insert
От: LaptevVV Россия  
Дата: 08.09.19 19:26
Оценка: 4 (1)
SVZ>А чего там накосячили?
SVZ>В код заглянул — без поллитры не разобрать. Где подвоха ждать?
Подвох был в быстродействии.
Студийная реализация работала в 5 раз медленней gccишной
Но в 17 и 19 студии не проверял.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: std::vector insert
От: LaptevVV Россия  
Дата: 08.09.19 19:27
Оценка:
M>Это не так. Насколько я знаю, большинство реализаций использует кэф 1.2 где-то. Он был признан оптимальным на все случаи жизни
Ну, раньше Саттер писал, что коэффициент порядка 1.7
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[6]: std::vector insert
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 08.09.19 19:46
Оценка: +1
Здравствуйте, LaptevVV, Вы писали:

M>>Это не так. Насколько я знаю, большинство реализаций использует кэф 1.2 где-то. Он был признан оптимальным на все случаи жизни

LVV>Ну, раньше Саттер писал, что коэффициент порядка 1.7

Возможно, я ошибаюсь

GCC 8.3 в два раза увеличивает — http://ideone.com/KVGPku
Маньяк Робокряк колесит по городу
Re[6]: std::vector insert
От: K13 http://akvis.com
Дата: 09.09.19 06:24
Оценка: 5 (2)
Здравствуйте, LaptevVV, Вы писали:

SVZ>>А чего там накосячили?

SVZ>>В код заглянул — без поллитры не разобрать. Где подвоха ждать?
LVV>Подвох был в быстродействии.
LVV>Студийная реализация работала в 5 раз медленней gccишной
LVV>Но в 17 и 19 студии не проверял.

там еще один подвох: я когда-то (наивный!) использовал std::deque для того, чтобы не требовался непрерывный блок памяти (иногда элементов было много, но при обработке очереди рассасывалось).

а потом при запуске с удивлением смотрел, как оно упало при добавлении в очередь 60-байтного элемента, потому что не получилось выделить 200 мегабайт одним куском (32-битная система, это было давно).

как оказалось, у студии очень маленький размер блока (и это не управляется) -- а список указателей на блоки хранится в одном std::vector (по смыслу).
Re[7]: std::vector insert
От: qaz77  
Дата: 09.09.19 14:09
Оценка:
Здравствуйте, K13, Вы писали:

K13>там еще один подвох: я когда-то (наивный!) использовал std::deque для того, чтобы не требовался непрерывный блок памяти (иногда элементов было много, но при обработке очереди рассасывалось).


K13>а потом при запуске с удивлением смотрел, как оно упало при добавлении в очередь 60-байтного элемента, потому что не получилось выделить 200 мегабайт одним куском (32-битная система, это было давно).


K13>как оказалось, у студии очень маленький размер блока (и это не управляется) -- а список указателей на блоки хранится в одном std::vector (по смыслу).


Хм. Указателей на блоки в списке получается около 50 млн.
Это какой же должен быть размер элемента и блока, чтобы все это в 2 гига влезало?

Сам использую std::deque для ухода от больших непрерывных блоков.
Обозначенную проблему не наблюдал. Правда для х86 упираюсь в 2 гига при примерно 5 млн. элементов deque.

Кто-нибудь разбирался, размер блоков фиксированный в байтах или элементах?
Re[8]: std::vector insert
От: WiseAlex Беларусь  
Дата: 10.09.19 06:29
Оценка: 5 (2)
Здравствуйте, qaz77, Вы писали:
Q>Кто-нибудь разбирался, размер блоков фиксированный в байтах или элементах?
в студии было в байтах (причем размер небольшой) и при превышении deque превращается в list — те один элемент в блоке
Re[9]: std::vector insert
От: Stanislav V. Zudin Россия  
Дата: 10.09.19 06:41
Оценка: 2 (1)
Здравствуйте, WiseAlex, Вы писали:

Q>>Кто-нибудь разбирался, размер блоков фиксированный в байтах или элементах?

WA>в студии было в байтах (причем размер небольшой) и при превышении deque превращается в list — те один элемент в блоке

Мдяяя
В 2017 Студии:

#define _DEQUESIZ    (sizeof (value_type) <= 1 ? 16 \
    : sizeof (value_type) <= 2 ? 8 \
    : sizeof (value_type) <= 4 ? 4 \
    : sizeof (value_type) <= 8 ? 2 \
    : 1)    /* elements per block (a power of 2) */
_____________________
С уважением,
Stanislav V. Zudin
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.