Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 10:22
Оценка: :)
Или я не до конца понимаю что есть сложность алгоритма или в описании какая то ошибка. Вообщем имеется:


    std::multiset<int> arr;
    //...
    while (set.size() > 1)
    {
        std::multiset<int>::const_iterator itA = arr.begin();
        std::multiset<int>::const_iterator itB = ++arr.begin();
        double c = *itA + *itB;
        set.erase(itA, ++itB);
        set.insert(c);
    }



Исходя из описания:
сложность erase log(N)+X (В данном случае X=2)
сложность insert log(N)

For the first version ( insert(x) ), logarithmic.
For the last version ( erase(first,last) ), logarithmic in container size plus linear in the distance between first and last.


Исходя из профилятора:
insert ~60%
erase ~11%

Вот как такое может быть? Компилятор MinGW. Тестировалось на 300000 эл.
Re: Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 10:26
Оценка:
Здравствуйте, st0nx, Вы писали:

S>Или я не до конца понимаю что есть сложность алгоритма или в описании какая то ошибка. Вообщем имеется:



S>
S>    std::multiset<int> arr;
S>    //...
S>    while (set.size() > 1)
S>    {
S>        std::multiset<int>::const_iterator itA = arr.begin();
S>        std::multiset<int>::const_iterator itB = ++arr.begin();
S>        double c = *itA + *itB;
S>        set.erase(itA, ++itB);
S>        set.insert(c);
S>    }
S>



S>Исходя из описания:

S>сложность erase log(N)+X (В данном случае X=2)
S>сложность insert log(N)

S>

S>For the first version ( insert(x) ), logarithmic.
S>For the last version ( erase(first,last) ), logarithmic in container size plus linear in the distance between first and last.


S>Исходя из профилятора:

S>insert ~60%
S>erase ~11%

S>Вот как такое может быть? Компилятор MinGW. Тестировалось на 300000 эл.


вырваный кусок косячный:

    std::multiset<int> arr;
    //...
    while (set.size() > 1)
    {
        std::multiset<int>::const_iterator itA = arr.begin();
        std::multiset<int>::const_iterator itB = ++arr.begin();
        double c = *itA + *itB;
        arr.erase(itA, ++itB);
        arr.insert(c);
   }
Re[2]: Скорость работы erase(first,last) и insert(x)
От: Muxa  
Дата: 06.05.11 10:37
Оценка:
знакомый код. тестовое задание в яндекс?
Re[3]: Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 10:40
Оценка:
Здравствуйте, Muxa, Вы писали:

M>знакомый код. тестовое задание в яндекс?


Ага. Разобрался со всеми кроме этой. Везде все логично а эта вводит в ступор.
Re: Скорость работы erase(first,last) и insert(x)
От: CreatorCray  
Дата: 06.05.11 10:49
Оценка:
Здравствуйте, st0nx, Вы писали:

S>Исходя из описания:

S>сложность erase log(N)+X (В данном случае X=2)
S>сложность insert log(N)

Дык классика: O1(log N) != O2(log N) потому как O разные
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re[4]: Скорость работы erase(first,last) и insert(x)
От: Muxa  
Дата: 06.05.11 10:51
Оценка:
M>>знакомый код. тестовое задание в яндекс?
S>Ага. Разобрался со всеми кроме этой. Везде все логично а эта вводит в ступор.
надо же, они даже исправили ошибку в этом задании, которую я нашел.

я так понял тебя смущает что сложность insert и erase одинакова (при Х = 2 = const), но реальное время выполнения отличается в 6 раз?
почему бы и нет?
увеличь размер массива в 10 раз и посмотри профайлером, ты должен получить теже самые проценты.
сложность != время выполнения.
сложность показывает во сколько раз изменится время выполнения при увеличении/уменьшении N.
Re[5]: Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 10:58
Оценка:
Здравствуйте, Muxa, Вы писали:

M>>>знакомый код. тестовое задание в яндекс?

S>>Ага. Разобрался со всеми кроме этой. Везде все логично а эта вводит в ступор.
M>надо же, они даже исправили ошибку в этом задании, которую я нашел.

M>я так понял тебя смущает что сложность insert и erase одинакова (при Х = 2 = const), но реальное время выполнения отличается в 6 раз?

M>почему бы и нет?
M>увеличь размер массива в 10 раз и посмотри профайлером, ты должен получить теже самые проценты.
M>сложность != время выполнения.
M>сложность показывает во сколько раз изменится время выполнения при увеличении/уменьшении N.

Если ты про использование erase(itA, ++itB); То не исправили. Изначально функция зацикливается потому что удаляется 1 эл.
Re: Скорость работы erase(first,last) и insert(x)
От: zaufi Земля  
Дата: 06.05.11 10:58
Оценка: 1 (1)
Здравствуйте, st0nx, Вы писали:

S>Исходя из описания:

S>сложность erase log(N)+X (В данном случае X=2)
S>сложность insert log(N)

S>Исходя из профилятора:

S>insert ~60%
S>erase ~11%

S>Вот как такое может быть? Компилятор MinGW. Тестировалось на 300000 эл.


ты путаешь теплое с мягким ))
сложность алгоритма не есть время исполнения!

вот представь себе, что твоя реализация STL такова, что одна вставка выполняется... ну, допустим 60нс, а удаление 10нс... ввиду например, не оптимального кода, контекста окружающего вставку и удаление в твоем алгоритме(какие-то данные при удалении уже оказались в кэше проца, и нормально выровнены и все такое прочее) ... ну вобщем миллион причин можно придумать... -- тогда при однаковой сложности log(N) время, которое проц проведет в функциях erase и insert очевидно будет разным, для одного и того же N!

достаточно ясно объяснил?
Re[2]: Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 10:58
Оценка:
Здравствуйте, CreatorCray, Вы писали:

CC>Здравствуйте, st0nx, Вы писали:


S>>Исходя из описания:

S>>сложность erase log(N)+X (В данном случае X=2)
S>>сложность insert log(N)

CC>Дык классика: O1(log N) != O2(log N) потому как O разные


Теперь понятно. Спасибо
Re[2]: Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 11:03
Оценка:
Здравствуйте, zaufi, Вы писали:

Z>Здравствуйте, st0nx, Вы писали:


S>>Исходя из описания:

S>>сложность erase log(N)+X (В данном случае X=2)
S>>сложность insert log(N)

S>>Исходя из профилятора:

S>>insert ~60%
S>>erase ~11%

S>>Вот как такое может быть? Компилятор MinGW. Тестировалось на 300000 эл.


Z>ты путаешь теплое с мягким ))

Z>сложность алгоритма не есть время исполнения!

Z>вот представь себе, что твоя реализация STL такова, что одна вставка выполняется... ну, допустим 60нс, а удаление 10нс... ввиду например, не оптимального кода, контекста окружающего вставку и удаление в твоем алгоритме(какие-то данные при удалении уже оказались в кэше проца, и нормально выровнены и все такое прочее) ... ну вобщем миллион причин можно придумать... -- тогда при однаковой сложности log(N) время, которое проц проведет в функциях erase и insert очевидно будет разным, для одного и того же N!


Z>достаточно ясно объяснил?


Да все достаточно понятно
Re[2]: Скорость работы erase(first,last) и insert(x)
От: rg45 СССР  
Дата: 06.05.11 11:54
Оценка: 1 (1) +1
Здравствуйте, zaufi, Вы писали:

Z>ты путаешь теплое с мягким ))

Z>сложность алгоритма не есть время исполнения!

+1

Хочу немного дополнить. Алгоритмическая сложность — это характеристика алгоритма, описывающая характер зависимости (линейная, логарифмическая, квадратичная и др.) времени работы алгоритма от размера входной последовательности. Но эта характеристика не только не позволяет вычислить абсолютное время выполнения алгоритма, но даже не позволяет сравнить по быстродействию два алгоритма для входной последовательности заданного конечного размера. Допустим, даны два алгоритма — один с квадратичной сложностью, другой — с логарифмической. на основании только лишь этой информации можно быть уверенным только лишь в том, что существует некоторое пороговое значение размера входной последовательности, выше которого алгоритм с логарифмической сложностью начинает выигрывать у алгоритма с квадратичной сложностью по времени выполнения. И выигрыш будет тем больше, чем больше размер входной последовательности. Каков этот пороговый размер, без дополнительных сведений об этих алгоритмах сказать невозможно. Вполне может оказаться, что для какого-то конкретного размера входной последовательности алгоритм с логарифмической сложностью будет выполняться дольше, чем алгоритм с квадратичной сложностью.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Скорость работы erase(first,last) и insert(x)
От: st0nx  
Дата: 06.05.11 12:15
Оценка:
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, zaufi, Вы писали:


Z>>ты путаешь теплое с мягким ))

Z>>сложность алгоритма не есть время исполнения!

R>+1


R>Хочу немного дополнить. Алгоритмическая сложность — это характеристика алгоритма, описывающая характер зависимости (линейная, логарифмическая, квадратичная и др.) времени работы алгоритма от размера входной последовательности. Но эта характеристика не только не позволяет вычислить абсолютное время выполнения алгоритма, но даже не позволяет сравнить по быстродействию два алгоритма для входной последовательности заданного конечного размера. Допустим, даны два алгоритма — один с квадратичной сложностью, другой — с логарифмической. на основании только лишь этой информации можно быть уверенным только лишь в том, что существует некоторое пороговое значение размера входной последовательности, выше которого алгоритм с логарифмической сложностью начинает выигрывать у алгоритма с квадратичной сложностью по времени выполнения. И выигрыш будет тем больше, чем больше размер входной последовательности. Каков этот пороговый размер, без дополнительных сведений об этих алгоритмах сказать невозможно. Вполне может оказаться, что для какого-то конкретного размера входной последовательности алгоритм с логарифмической сложностью будет выполняться дольше, чем алгоритм с квадратичной сложностью.


В таком случае есть ли еще какие либо методы сравнения алгоритмов и оценки алгоритмов, кроме как непосредственное тестирование или подсчета операций и их стоимости по ресурсам?
Re[4]: Скорость работы erase(first,last) и insert(x)
От: rg45 СССР  
Дата: 06.05.11 13:42
Оценка:
Здравствуйте, st0nx, Вы писали:

S>В таком случае есть ли еще какие либо методы сравнения алгоритмов и оценки алгоритмов, кроме как непосредственное тестирование или подсчета операций и их стоимости по ресурсам?


Такие, чтоб и универсальные и надежные — вряд ли. ИМХО, полагаться можно только на результаты тестирования.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[4]: Скорость работы erase(first,last) и insert(x)
От: jazzer Россия Skype: enerjazzer
Дата: 06.05.11 16:09
Оценка:
Здравствуйте, st0nx, Вы писали:

S>В таком случае есть ли еще какие либо методы сравнения алгоритмов и оценки алгоритмов, кроме как непосредственное тестирование или подсчета операций и их стоимости по ресурсам?


Математики возятся, но все это уже не имеет никакого значения, потомоу что у нас оптимизирующие компиляторы и очень сложные системы вычислений (3 уровня кеша, регистры, инлайнинг, предсказание переходов и прочая), так что говорить о стоимости какой-то элементарной операции малоосмысленно, потому что влезет какой-нть кэш и испортит всю малину.
Так что только мерять.
Пиши тест для разных входных данных, включай его в систему ночных тестов, и пусть он все время крутится и показывает, как у тебя что меняется в зависимости от того, что ты добавил, скажем, еще один член в свою структуру, или поменял бибилотеку/компилятор. Эффекты могут быть самые разнообразные.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Скорость работы erase(first,last) и insert(x)
От: jazzer Россия Skype: enerjazzer
Дата: 06.05.11 16:15
Оценка: 8 (1)
Здравствуйте, rg45, Вы писали:

R>Вполне может оказаться, что для какого-то конкретного размера входной последовательности алгоритм с логарифмической сложностью будет выполняться дольше, чем алгоритм с квадратичной сложностью.


+1

Вот неплохая иллюстрация того, как общеизвестно медленный алгоритм сортировки вставками оказывается самым быстрым в определенной ситуации:
http://rsdn.ru/forum/humour/4233016.aspx
Автор: jazzer
Дата: 14.04.11
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Скорость работы erase(first,last) и insert(x)
От: kvser  
Дата: 06.05.11 17:00
Оценка: 8 (1) +1
Здравствуйте, jazzer, Вы писали:

J> ... оптимизирующие компиляторы и очень сложные системы вычислений (3 уровня кеша, регистры, инлайнинг, предсказание переходов и прочая), так что говорить о стоимости какой-то элементарной операции малоосмысленно, потому что влезет какой-нть кэш и испортит всю малину.


отсюда
Автор: remark
Дата: 25.04.08

Возьмём вот такую простенькую функцию перемножения матриц:

void multiply(T* X, T* Y, T* Z, int size)
{
    for (int i = 0; i != size; ++i)
        for (int j = 0; j != size; ++j)
            for (int k = 0; k != size; ++k)
                Z[i*size+j] += X[i*size+k] * Y[k*size+j];
}

Запускаю для матриц размера 512 — результат 16.9 секунды.
Запускаю для матриц размера 513... делайте ставки, господа! Результат 4.8 секунды!
Причина кроется в паттерне прохода по матрице Y во внутреннем цикле. При размере матрицы 512 размер строки матрицы составляет 4096 байт (8-байтовые элементы). Соответственно адреса элементов Y[0][0] и Y[1][0] имеют одинаковые младшие 12 бит. Это вызывает постоянные конфликты в кэше с вытеснением старых данных.

 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.