С Новым годом! Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.57/7: Рейтинг темы: голосов - 7, средняя оценка - 4.57
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5

Довольно большое время работы с std::min()

05.12.2014, 08:55. Показов 1499. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здравствуйте! Имеется 2 исходника.
1:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <utility>
#include <cctype>
#include <iterator>
#include <cmath>
 
#define x first
#define y second
#define pb push_back
#define mp make_pair
#define ins insert
 
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll, ll> pii;
typedef pair<ld, ld> pdd;
 
const ll maxn = 1000009;
 
ll n, m, i, j, k;
vector<ll> p;
int f[maxn];
 
inline void test()
{
    f[1] = 1; f[2] = 2; f[3] = 3;
    for (ll i = 1; i <= 100; ++i)
        p.pb(i*i*i);
    cin >> n;
    for (ll i = 4; i <= n; ++i)
    {
        f[i] = 1000000009;
        for (ll j = 0; j<p.size(); ++j)
        {
            if (i >= p[j] && f[i] > f[i - p[j]] + 1)
                f[i] = f[i - p[j]] + 1;
        }
    }
    cout << f[n];
    //system("pause");
}
 
 
int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    //ios_base::sync_with_stdio(0);
    //cin.tie(0);
    test();
    //system("pause");
    return 0;
}
2:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <utility>
#include <cctype>
#include <iterator>
#include <cmath>
 
#define x first
#define y second
#define pb push_back
#define mp make_pair
#define ins insert
 
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pii;
typedef pair<ld,ld> pdd;
 
const ll maxn=1000009;
 
ll n,m,i,j,k;
vector<ll> p;
ll f[maxn];
 
void test()
{
    f[1]=1;f[2]=2;f[3]=3;
    for(ll i=1;i<=100;++i)
        p.pb(i*i*i);
    cin>>n;
    for(ll i=4;i<=n;++i)
    {
        f[i]=1000000009;
        for(ll j=0;j<p.size();++j)
        {
            if(i>=p[j])
                f[i]=min(f[i],f[i-p[j]]+1);
            else
                break;
        }
    }
    cout<<f[n];
}
 
 
int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    //ios_base::sync_with_stdio(0);
    //cin.tie(0);
    test();
    //system("pause");
    return 0;
}
Исходники абсолютно идентичны, за исключением одной строки : в 1-ом коде ипользовано условие
C++
1
if (i >= p[j] && f[i] > f[i - p[j]] + 1)
для замены std::min во 2-ом исходнике.

Самое интересное : при сдаче задачи в тестирующую систему программа с этим if'ом заходит с довольно большим запасом по времени, тогда как версия с std::min ловит Time Limit и по моим замерам работает в 4-5 раз дольше.

Кто может обьяснить, почему так происходит? Неужели вызов функции настолько замедляет программу каждый раз? Функция std::min элементарна же.(вариант со своим, самописным min с inline и без шаблонов я не тестил).
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
05.12.2014, 08:55
Ответы с готовыми решениями:

Большое время работы
Добрый вечер, форумчане! Возникла проблема : у программы чтения файла очень большой runtime(пишу на codeblocks). Что с этим...

Std::min
Подскажите, пожалуйста, как расписать эту функцию M = std::min(M, sin(m)); Не из потока std, а в виде обычной функции. Вот весь код: ...

Из переменной типа std::string записать в файл большое количество данных (2 Mb)
Нужно записать в файл большое количество данных. Предполагается, что в переменной большое количество строк следовательно `&gt;&gt;` не...

14
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
05.12.2014, 09:31
ZaMaZaN4iK, как минимум, у Вас во втором случае присваивание происходит чаще.
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
05.12.2014, 09:39
ZaMaZaN4iK, не по теме, но с вектором у тебя беда. Сделай p.reserve(100) перед циклом:
C++
1
2
3
p.reserve(100);
for(ll i=1;i<=100;++i)
        p.pb(i*i*i);
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12930 / 6798 / 1819
Регистрация: 18.10.2014
Сообщений: 17,206
05.12.2014, 09:59
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
Исходники абсолютно идентичны,
Да что вы говорите???

Смотрим в первый

C++
1
2
3
4
5
for (ll j = 0; j<p.size(); ++j)
{
  if (i >= p[j] && f[i] > f[i - p[j]] + 1)
    f[i] = f[i - p[j]] + 1;
}
Смотрим во второй

C++
1
2
3
4
5
6
7
for(ll j=0;j<p.size();++j)
{
  if(i>=p[j])
    f[i]=min(f[i],f[i-p[j]]+1);
  else
    break;
}
Что-то я не вижу этого 'break' в первом исходнике.
0
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5
05.12.2014, 11:33  [ТС]
TheCalligrapher, прошу прощения. Не тот исходник добавил. В том, про который я веду речь, этот самый break стоит.Так что тут с меня взятки гладки

DrOffset, Да, я знаю. Можно и reserve(), можно и сразу размер указать. Не суть важно. На таком размере массива(а размер всего лишь сто) произойдет всего лишь 8 перевыделений памяти. Хоть это и медленная операция, но здесь она не играет ключевую роль. А так да,конечно, Вы правы. Просто лень писать было(хоть это и глупо звучит )

Toshkarik, ну я понимаю это. Но что, операция присваивания такая долгая что ли?

Добавлено через 4 минуты
TheCalligrapher, не туда я посмотрел. На самом деле тот код даже без break работает быстрее. И если я там этот break поставлю, то это наоборот будет только оптимизация, а не замедление кода.

Добавлено через 1 минуту
И там кстати нужно писать break с условием, иначе будет неправильный ответ
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
05.12.2014, 12:05
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
На таком размере массива(а размер всего лишь сто) произойдет всего лишь 8 перевыделений памяти
Ты не можешь знать сколько произойдет перевыделений на машине, где прогоняется тест. Там и компилятор и ОС и стандартная библиотека совсем не обязательно будут совпадать с твоими. Раз уж пишешь задачки на скорость, то нужно ответственно к этому относиться. В любом случае, динамическое выделение памяти - это одна из самых затратных операций в твоей программе.
0
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5
05.12.2014, 13:04  [ТС]
DrOffset, да, я обычно память резервирую,но хочу Ваше внимание, что не это место узкое в моей программе, этот оптимайз на максимальных данных(а это повторюсь всего лишь 100), даёт выигрыш на самом большом тесте всего лишь 4 сотых секунды.Вы мне лучше помогите с тем местом, на которое я обратил Ваше внимание.

Я не просто знаю, я уверен, что там будет не более 8 первыделений памяти. Так как по стандарту вектор увеличивает свой размер в 2 раза по сравнению с предыдущим. Ну и тут просто логарифм возьмем и получим, что 8-9 перевыделений. И хоть это операция долгая, я не спорю, она так мало раз выполняется, что не это ключевое место в моем коде. Версия компилятора на сайте была также указана и она совпадает с моим(также, как и флаги компиляции). А STL'овский вектор только таким способ память перевыделяет.
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
05.12.2014, 13:08
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
Так как по стандарту вектор увеличивает свой размер в 2 раза по сравнению с предыдущим.
По какому, интересно, стандарту? Неправда это.

По теме: попробуйте использовать профилировщик.
0
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5
05.12.2014, 13:12  [ТС]
Toshkarik, прошу прощения за может быть неправильно понятое выражение. Стандартом я имел в виду стандартную реализацию vector в STL. Вот ссылка на Хабр : тыц
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
05.12.2014, 13:16
ZaMaZaN4iK, это зависит от компилятора, от конкретной реализации STL. Были компиляторы и с 1.5 и c 1.7 и с 2.5 множителями. Правда, версии сейчас не вспомню.

Добавлено через 1 минуту
Вот, что то нашел: http://alenacpp.blogspot.ru/2005/06/vector_30.html
1
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5
05.12.2014, 13:23  [ТС]
Toshkarik, да, спасибо за ссылку. Тоже читал. Только что замерил свой коэффициент - 2. К сожалению, у меня используется наихудший. Из этого следует, что хуже моего варианта не будет точно

Добавлено через 1 минуту
Toshkarik, Вы не подскажете, так в чём может быть проблема всё таки ? тут явно дело не в перераспрделении памяти. Так как во первых, в двух исходниках используется один и тот же вариант, а во вторых, я уже протестил уже и с reserve(). Неужели операция присваивания так много занимает времени? Или вызов функции std::min() такой долгий?
0
 Аватар для Toshkarik
1181 / 894 / 94
Регистрация: 03.08.2011
Сообщений: 2,461
05.12.2014, 13:30
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
Или вызов функции std::min() такой долгий?
Нет. Даже больше скажу, она скорей всего инлайнится. Дело не в ней. Если у Вас есть пример с большим количеством данных, то попробуйте сделать для теста счетчик в первом и во втором случаях.
C++
1
2
3
4
if (i >= p[j] && f[i] > f[i - p[j]] + 1) {
   f[i] = f[i - p[j]] + 1;
   cnt++;
}
C++
1
2
3
4
5
if(i>=p[j]) {
   f[i]=min(f[i],f[i-p[j]]+1);
   cnt++;
} else
      break;
И сравните их.
0
Мой лучший друг-отладчик!
 Аватар для ZaMaZaN4iK
167 / 167 / 30
Регистрация: 24.06.2012
Сообщений: 662
Записей в блоге: 5
05.12.2014, 13:34  [ТС]
Только что написал свою функцию min:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <string>
#include <cstring>
#include <vector>
#include <algorithm>
#include <utility>
#include <cctype>
#include <iterator>
#include <cmath>
 
#define x first
#define y second
#define pb push_back
#define mp make_pair
#define ins insert
 
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pii;
typedef pair<ld,ld> pdd;
 
const ll maxn=1000009;
 
ll n,m,i,j,k;
vector<ll> p;
ll f[maxn];
 
ll mini(ll a,ll b)
{
    if(a<=b)    return a;
    else    return b;
}
 
void test()
{
    f[1]=1;f[2]=2;f[3]=3;
    for(ll i=1;i<=100;++i)
        p.pb(i*i*i);
    cin>>n;
    for(ll i=4;i<=n;++i)
    {
        f[i]=1000000009;
        for(ll j=0;j<p.size();++j)
        {
            if(i>=p[j])
                f[i]=mini(f[i],f[i-p[j]]+1);
            else
                break;
        }
    }
    cout<<f[n];
}
 
 
int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    //ios_base::sync_with_stdio(0);
    //cin.tie(0);
    test();
    //system("pause");
    return 0;
}
С ней задача заходит. Но эта версия работает на 0.2 секунды дольше версии с if

Добавлено через 3 минуты
Toshkarik, да,я делал это. В случае с min оно, понятное дело, больше. Это сразу понятно. Получается, что программа тормозит из-за того, что очень много раз выполняется операция присваивания... Но я никак не мог предположить, что эта операция может долго выполняться.
0
Диванный эксперт
Эксперт С++
 Аватар для Max Dark
2550 / 2064 / 971
Регистрация: 09.10.2013
Сообщений: 4,793
Записей в блоге: 4
05.12.2014, 14:01
Как заставить компилятор C/C++ генерировать плохой код
1
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
05.12.2014, 14:25
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
Вы мне лучше помогите с тем местом, на которое я обратил Ваше внимание.
Вроде бы выше уже дали ответ. Код неэквивалентен. Операций в коде с std::min больше и выполняются они чаще. Сам по себе вызов std::min инлайнится и накладных расходов на его вызов нет. Можно переписать так, результат будет таким же:
C++
1
2
3
4
            if(i >= p[j])
            {
                f[i] = f[i] < f[i - p[j]] + 1 ? f[i] : f[i - p[j]] + 1;
            }
Поэтому решение одно: корректируй алгоритм, чтобы избежать лишних операций и будет тебе счастье. Сам по себе std::min в твоих бедах не виноват.

Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
Я не просто знаю, я уверен, что там будет не более 8 первыделений памяти. Так как по стандарту вектор увеличивает свой размер в 2 раза по сравнению с предыдущим.
Вот про два раза в стандарте как раз ничего нет. Это диктуется стратегией выделения памяти, которую определяет разработчик стандартной библиотеки. Следовательно, зависит от реализации (да, в g++ увеличивается действительно в 2 раза, но это еще не значит, что это какой-либо стандарт). Но если этот вопрос вызывает такую негативную реакцию у тебя, то ладно, мне в принципе все равно.

Добавлено через 4 минуты
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
тут явно дело не в перераспрделении памяти.
Причем я выше явно указал, что дело не в этом. Когда я сказал про распределение памяти, то указал, что это замечание к теме не относится. Но твое восприятие в штыки моих комментариев не дало этой информации усвоится

Добавлено через 11 минут
Цитата Сообщение от ZaMaZaN4iK Посмотреть сообщение
Получается, что программа тормозит из-за того, что очень много раз выполняется операция присваивания... Но я никак не мог предположить, что эта операция может долго выполняться.
Перекачка из регистра в память и обратно и как минимум одно дополнительное условие. Можно приблизительно оценить размер бедствия, если посмотреть что сгененировал компилятор. Получаешь два ассемблерных листинга, потом натравливаешь какую-нибудь утилиту, вроде diff, и смотришь разницу.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
05.12.2014, 14:25
Помогаю со студенческими работами здесь

Большое время перерисовки OpenGL
Здравствуйте, я студент 2 курса, учусь на программиста, решил начать писать какую ни будь простенькую изометрическую игрушку, и наткнулся...

Массив: Получить min(a1;a2;a3)+min(a4;a5;a6)+min(a7;a8;a9)+min(a10;a11;a12) .
Заполнить массив а1,а2,а3...а12 случайными числами от 0 до 20. Получить min(a1;a2;a3)+min(a4;a5;a6)+min(a7;a8;a9)+min(a10;a11;a12) .

Большое расхождение в результатах работы программы
#include &lt;iostream&gt; #include &lt;cmath&gt; #include &lt;math.h&gt; using namespace std; void main() { float eps, x, a, b, ax, bx,...

Не воспринимает ни std::cout, ни std::cin. Вобщем ничего из std. Также не понимает iostream
Здравствуйте! Я хотел начать изучать язык C++. Набрал литературы. Установил Microsoft Visual C++ 2005 Express Edition. Образ диска...

Отсортировать большое число элементов за минимальное время, используя битовый массив
Всем привет! Вот, получил задание такое: написать сортировку большого числа элементов за минимальное время, используя битовый массив....


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение. И на уровне агентов добавится между грибами или бактериями взаимодействий. До того я пробовал подход через многомерные массивы,. . .
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru