Здравствуйте, LaptevVV, Вы писали:
SVZ>>А чего там накосячили? SVZ>>В код заглянул — без поллитры не разобрать. Где подвоха ждать? LVV>Подвох был в быстродействии. LVV>Студийная реализация работала в 5 раз медленней gccишной LVV>Но в 17 и 19 студии не проверял.
там еще один подвох: я когда-то (наивный!) использовал std::deque для того, чтобы не требовался непрерывный блок памяти (иногда элементов было много, но при обработке очереди рассасывалось).
а потом при запуске с удивлением смотрел, как оно упало при добавлении в очередь 60-байтного элемента, потому что не получилось выделить 200 мегабайт одним куском (32-битная система, это было давно).
как оказалось, у студии очень маленький размер блока (и это не управляется) -- а список указателей на блоки хранится в одном std::vector (по смыслу).
Здравствуйте, qaz77, Вы писали: Q>Кто-нибудь разбирался, размер блоков фиксированный в байтах или элементах?
в студии было в байтах (причем размер небольшой) и при превышении deque превращается в list — те один элемент в блоке
Здравствуйте, ahaos, Вы писали:
A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.
A>Делается это так. A>res.insert(res.begin(), a.begin(), a.end());
Не к тому концу вы добавляете элементы.
A>При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех.
Не удивительно.
A>Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще. Сортировка массивов res, a не допустима.
SVZ>А чего там накосячили? SVZ>В код заглянул — без поллитры не разобрать. Где подвоха ждать?
Подвох был в быстродействии.
Студийная реализация работала в 5 раз медленней gccишной
Но в 17 и 19 студии не проверял.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, 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
Здравствуйте, 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 непосредственно.
Здравствуйте, LaptevVV, Вы писали:
LVV>Может так пойдет: ? LVV>1. Поэлементно добавляешь в конец вектора операцией pus_back() LVV>2. Поэлементно обмениваешь с первыми элементами вектора
3. Заменить std::vector на std::deque? Если нужна вставка непременно в начало.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, ahaos, Вы писали:
A>Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение. A>Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять
Надо не выделять — не задавать размер вектора, а резервировать — методом reserve, а потом добавлять, как и делал раньше
Здравствуйте, LaptevVV, Вы писали:
M>>Это не так. Насколько я знаю, большинство реализаций использует кэф 1.2 где-то. Он был признан оптимальным на все случаи жизни LVV>Ну, раньше Саттер писал, что коэффициент порядка 1.7
В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.
Делается это так.
res.insert(res.end(), a.begin(), a.end()); (исправлено)
При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех.
Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще. Сортировка массивов res, a не допустима.
Здравствуйте, ahaos, Вы писали:
A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.
A>Делается это так. A>res.insert(res.begin(), a.begin(), a.end());
A>При ближайшем рассмотрении оказалось, что это самая затратная по времени операция в цикле из всех. A>Можно ли как-нибудь оптимизировать данный процесс штатными средствами STL или каким-либо еще. Сортировка массивов res, a не допустима.
Могу предположить, что идет постоянное перераспределение памяти. Можно попробовать навскидку оценить размер финального вектора, и зарезервировать нужное количество элементов
A>В цикле выполняются какие-то операции и формируется массив a с элементами long double, который каждую итерацию цикла должен добавляться к концу массива res.
Отсортированный или нет? A>Делается это так. A>res.insert(res.begin(), a.begin(), a.end());
Добавляешь в начало.
Может так пойдет: ?
1. Поэлементно добавляешь в конец вектора операцией pus_back()
2. Поэлементно обмениваешь с первыми элементами вектора
При большом размере вектора перераспределение памяти делается редко.
Как правило, в конце вектора память уже выделена.
Так что отследи только, что с чем в каком порядке менять из конца в начало.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, 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>Так что отследи только, что с чем в каком порядке менять из конца в начало.
Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение.
Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять
A>Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение. A>Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять
Дело в том, что при выполнении операции push_back() вектор при нехватке памяти сам выделяет новое место.
И выделяет не по 1 элементу, а сразу столько же, сколько в векторе имеется.
Поэтому с увеличением вектора новая память выделяется все реже.
Но если хотя бы примерно известен наибольший размер, то да, лучше заранее выделить столько 1 раз, и уже не париться.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
SVZ>3. Заменить std::vector на std::deque? Если нужна вставка непременно в начало.
Это да. Только не в студийной реализации — там дек реализован очень плохо.
В gcc — все гораздо лучше.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
SVZ>>3. Заменить std::vector на std::deque? Если нужна вставка непременно в начало. LVV>Это да. Только не в студийной реализации — там дек реализован очень плохо.
А чего там накосячили?
В код заглянул — без поллитры не разобрать. Где подвоха ждать?
LVV>В gcc — все гораздо лучше.
Увы, нам не актуально.
_____________________
С уважением,
Stanislav V. Zudin
Здравствуйте, LaptevVV, Вы писали:
A>>Там была опечатка. Добавляется не в начало, а в конец вектора. Несмотря на это торможение. A>>Может действительно попробовать, как ранее писали. Сначала выделить место для вектора, а потом уже в него что-то писать? а не добавлять LVV>Дело в том, что при выполнении операции push_back() вектор при нехватке памяти сам выделяет новое место. LVV>И выделяет не по 1 элементу, а сразу столько же, сколько в векторе имеется.
Это не так. Насколько я знаю, большинство реализаций использует кэф 1.2 где-то. Он был признан оптимальным на все случаи жизни
M>Это не так. Насколько я знаю, большинство реализаций использует кэф 1.2 где-то. Он был признан оптимальным на все случаи жизни
Ну, раньше Саттер писал, что коэффициент порядка 1.7
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, K13, Вы писали:
K13>там еще один подвох: я когда-то (наивный!) использовал std::deque для того, чтобы не требовался непрерывный блок памяти (иногда элементов было много, но при обработке очереди рассасывалось).
K13>а потом при запуске с удивлением смотрел, как оно упало при добавлении в очередь 60-байтного элемента, потому что не получилось выделить 200 мегабайт одним куском (32-битная система, это было давно).
K13>как оказалось, у студии очень маленький размер блока (и это не управляется) -- а список указателей на блоки хранится в одном std::vector (по смыслу).
Хм. Указателей на блоки в списке получается около 50 млн.
Это какой же должен быть размер элемента и блока, чтобы все это в 2 гига влезало?
Сам использую std::deque для ухода от больших непрерывных блоков.
Обозначенную проблему не наблюдал. Правда для х86 упираюсь в 2 гига при примерно 5 млн. элементов deque.
Кто-нибудь разбирался, размер блоков фиксированный в байтах или элементах?