Какой вариант быстрее?
От: shvonder Россия  
Дата: 01.12.09 10:45
Оценка:
Какой вариант быстрее?

Случай 1
int N = 10 000;
list<MyStruct> List(N);

//Вариант 1
MyStruct Struct =  *lower_bound(List...)

//Вариант 2
vector<MyStruct> Vector(N);
copy(Vector<-List...);
MyStruct Struct =  *lower_bound(Vector...)


Случай 2
int N = 10 000;
list<MyStruct> List(N);

//Вариант 1
List->sort();

//Вариант 2
vector<MyStruct> Vector(N);
copy(Vector<-List...);
sort(Vector);
copy(List<-Vector...);
Re: Какой вариант быстрее?
От: remark Россия http://www.1024cores.net/
Дата: 01.12.09 10:54
Оценка:
Здравствуйте, shvonder, Вы писали:

S>Какой вариант быстрее?


А самому запустить под time?


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Какой вариант быстрее?
От: denisko http://sdeniskos.blogspot.com/
Дата: 01.12.09 10:57
Оценка:
Здравствуйте, shvonder, Вы писали:

S>Какой вариант быстрее?


S>Случай 1

S>
S>int N = 10 000;
S>list<MyStruct> List(N);

S>//Вариант 1
S>MyStruct Struct =  *lower_bound(List...)

S>//Вариант 2
S>vector<MyStruct> Vector(N);
S>copy(Vector<-List...);
S>MyStruct Struct =  *lower_bound(Vector...)
S>


S>Случай 2

S>
S>int N = 10 000;
S>list<MyStruct> List(N);

S>//Вариант 1
List->>sort();

S>//Вариант 2
S>vector<MyStruct> Vector(N);
S>copy(Vector<-List...);
S>sort(Vector);
S>copy(List<-Vector...);
S>

В смысле "алгоритмической сложности"
В случае 1 вариант 2 засчет того, что итераторы ветора RandomAcess
В случае 2 скорее вариант 1, поскольку лишнее копирование избегается
В реальной жизни на малых массивах не заметишь скорее всего, основной источник тормозов будет проверки и синхронизация (если стоит по дефолту).
<Подпись удалена модератором>
Re[2]: Какой вариант быстрее?
От: remark Россия http://www.1024cores.net/
Дата: 01.12.09 11:14
Оценка:
Здравствуйте, denisko, Вы писали:

D>В смысле "алгоритмической сложности"

D>В случае 1 вариант 2 засчет того, что итераторы ветора RandomAcess

Каким образом?
Вариант 1: lower_bound() выполняется за О(N) (последовательный просмотр).
Вариант 2: copy() выполняется за О(N) + lower_bound() за O(logN).
Итого оба варианта О(N). Только в первом варианте мы проходим в среднем по половине списка, что бы найти элемент, во-втором варианте мы проходим по всему списку + делаем копию + делаем бинарный поиск.
з.ы. это в предположении, что сравнение элементов занимает сравнимое время с чтениями/копированиями/итд.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re: Какой вариант быстрее?
От: Sni4ok  
Дата: 01.12.09 11:21
Оценка:
Здравствуйте, shvonder, Вы писали:

S>Какой вариант быстрее?


lower_bound требует random access iterator, чего у листа нету, поэтому std::find_if будет в первом случае самым быстрым вариантом, а во втором, очевидно самым быстрым вариантом будет метод list'а — sort, хоть сортировка и stable, а вообще список это плохой выбор для хранения отсортированных данных, ибо факт сортировки недают никакого прироста производительности, стоит задумать о выборе вектора, дека или множества.
Re[2]: Какой вариант быстрее?
От: shvonder Россия  
Дата: 01.12.09 11:28
Оценка:
Здравствуйте, Sni4ok, Вы писали:

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


S>>Какой вариант быстрее?


S>lower_bound требует random access iterator, чего у листа нету, поэтому std::find_if будет в первом случае самым быстрым вариантом, а во втором, очевидно самым быстрым вариантом будет метод list'а — sort, хоть сортировка и stable, а вообще список это плохой выбор для хранения отсортированных данных, ибо факт сортировки недают никакого прироста производительности, стоит задумать о выборе вектора, дека или множества.


Мне нужно 1)удалять элементы из списка 2)быстро находить по ключу. Какой контейнер нужен, как вы считаете?
А почему факт сортировки не даёт ? lower_bound — это разве не бинарный поиск ?
Re[3]: Какой вариант быстрее?
От: Sni4ok  
Дата: 01.12.09 11:36
Оценка:
Здравствуйте, shvonder, Вы писали:

S>Мне нужно 1)удалять элементы из списка 2)быстро находить по ключу. Какой контейнер нужен, как вы считаете?

S>А почему факт сортировки не даёт ? lower_bound — это разве не бинарный поиск ?

бинарный, но требует random access iterator'а, раз нужно удалять элементы, на вашем месте я бы выбрал std::set, возможно даже с boost::fast_pool_allocator в качесте аллокатора(тут правда есть ньюансы, если контейнер очень большой с огромным колл. эллементов(миллионы), то
boost::pool неподходит в силу сложности освобождения памяти O(N)).
Re[3]: Какой вариант быстрее?
От: shvonder Россия  
Дата: 01.12.09 11:36
Оценка:
Здравствуйте, remark, Вы писали:

R>Вариант 1: lower_bound() выполняется за О(N) (последовательный просмотр)....мы проходим в среднем по половине списка, что бы найти элемент.


Вот VS-реаизация. На мой нескушённый взгяд, это — бинарный поиск, токо advance для list'a развернётся в цикл.Или я неправ ?

template<class _FwdIt,
    class _Ty,
    class _Diff> inline
    _FwdIt _Lower_bound(_FwdIt _First, _FwdIt _Last, const _Ty& _Val, _Diff *)
    {    // find first element not before _Val, using operator<
    _DEBUG_ORDER_SINGLE(_First, _Last, true);
    _Diff _Count = 0;
    _Distance(_First, _Last, _Count);

    for (; 0 < _Count; )
        {    // divide and conquer, find half that contains answer
        _Diff _Count2 = _Count / 2;
        _FwdIt _Mid = _First;
        std::advance(_Mid, _Count2);
        _DEBUG_ORDER_SINGLE(_Mid, _Last, false);

        if (_DEBUG_LT(*_Mid, _Val))
            _First = ++_Mid, _Count -= _Count2 + 1;
        else
            _Count = _Count2;
        }
    return (_First);
    }
Re[3]: Какой вариант быстрее?
От: denisko http://sdeniskos.blogspot.com/
Дата: 01.12.09 15:45
Оценка:
Здравствуйте, remark, Вы писали:

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


D>>В смысле "алгоритмической сложности"

D>>В случае 1 вариант 2 засчет того, что итераторы ветора RandomAcess

R>Каким образом?

Я ступил копи не заметил.
<Подпись удалена модератором>
Re: Какой вариант быстрее?
От: Кодт Россия  
Дата: 01.12.09 16:30
Оценка:
Здравствуйте, shvonder, Вы писали:

S>Какой вариант быстрее?


S>Случай 1

S>
S>int N = 10 000;
S>list<MyStruct> List(N);

S>//Вариант 1
S>MyStruct Struct =  *lower_bound(List...)

S>//Вариант 2
S>vector<MyStruct> Vector(N);
S>copy(Vector<-List...);
S>MyStruct Struct =  *lower_bound(Vector...)
S>

В первом варианте — линейный поиск по списку. Во втором — линейное копирование, затем логарифмический поиск.
Даст выигрыш только в том случае, если операция сравнения существенно медленнее операции обмена.
Такое может быть в реальных условиях, например, если
struct MyStruct
{
    const char* m_shared_text; // любой способ разделяемого владения - начиная от глобального словаря
};
bool operator < (MyStruct const& a, MyStruct const& b) { return *a.m_shared_text < *b.m_shared_text; }

естественно, при достаточно длинных строках.

S>Случай 2

S>
S>int N = 10 000;
S>list<MyStruct> List(N);

S>//Вариант 1
S>List->sort();

S>//Вариант 2
S>vector<MyStruct> Vector(N);
S>copy(Vector<-List...);
S>sort(Vector);
S>copy(List<-Vector...);
S>

Сортировка списка — линейно-логарифмическая, без обменов.
Сортировка массива — тоже линейно-логарифмическая, но уже с обменами. Плюс оверхед на копирование туда-обратно.
Даст выигрыш, если
— MyStruct имеет небольшой размер, так, что обмен элементов совершается быстрее, чем обмен четырёх указателей при переносе узла списка
— вектор влезет в несколько линеек кэша, тогда как список окажется раскидан по памяти
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.