- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 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
#include <iostream>
#include <thread>
#include <list>
#include <functional>
#include <chrono>
using namespace std;
void outputToSomeContainer(int val, list<int>& result){
result.push_back(val);
}
class async{
list<thread> a;
public:
async(){}
async(async&& a): a(move(a.a))
{}
void addTask(function<void()>&&f){
a.emplace_back(move(f));
}
void wait(){
for(auto&& i: a)
i.join();
}
};
async async_O_n_Sort(const list<char>& unsorted, function<void(int)> outputToContainer){
async a;
for(int i: unsorted)//O(n)
a.addTask([i, outputToContainer](){this_thread::sleep_for(chrono::milliseconds(5+i*10));outputToContainer(i);});
return a;
}
int main() {
list<char> unsorted {1, 0, 6, 3, 4};
list<int> sorted;
auto a = async_O_n_Sort(unsorted, bind(outputToSomeContainer, placeholders::_1, ref(sorted)));
cout<<"А мы веселые пельменья, мы похоже на варенья"<<endl;
a.wait();
for(int i: sorted)
cout<<i<<endl;
return 0;
}
laMer007 05.01.2015 19:41 # 0
3.14159265 05.01.2015 22:11 # +1
Кстати какая самая недорогая по памяти сортировка с приемлимой (до квадратичной) сложностью, в треде как я понял советуют:
том 3 Кнута упражение 18 раздел 5.2.4
Dummy00001 05.01.2015 23:03 # 0
ага. конечно. с какой константой? небось 2^64 для 64-битных систем? :)
давно когда-то читал бумажку чудака который O(1) структурами занимается. там все очень и очень нетривиально и константы в этом O(1) просто заоблачные. даже в случае если делать нативно в железе.
3.14159265 05.01.2015 23:18 # 0
Пузырёк же.
Dummy00001 05.01.2015 23:54 # 0
O-нотация отражает только асимптотическую зависимость производительности от количества входных элементов, стремящегося к бесконечности. Поэтому константы как правило опускаются.
Но часто когда анализируются алгоритмы, народ так же записывает и константы (и другие асимптотически незначительные функции). Например: вместо O(n) пишут (например) O(5n + 10). что значит что у алгоритма, на каждый элемент есть избыточность 5, плюс 10 на инициализацию/деинициализацию.
В частности в области O(1) алгоритмов, т.к. асимптотика заранее известна, народ соосредотачивается на константе, которая отражает избыточность алгоритма.
Формального определения для юнита констант я не видел. Народ либо Кнутовским MIXом пользуется, либо количеством CPU циклов на каком-то настоящем проце.
> Пузырёк же.
где?
3.14159265 06.01.2015 00:40 # +1
>где?
Пример сортировки с честной O(1) по памяти без страшных констант и скрытых рекурсивных комиссий.
gost 06.01.2015 16:58 # 0
3.14159265 06.01.2015 17:14 # +2
while (!sorted(array)) shuffle(array);
Божественный one-liner.
Soul_re@ver 08.01.2015 03:04 # 0
LispGovno 08.01.2015 11:07 # 0
roman-kashitsyn 08.01.2015 11:46 # −1
Soul_re@ver 08.01.2015 13:28 # +3
laMer007 05.01.2015 22:06 # +1
laMer007 05.01.2015 22:08 # 0
http://rextester.com/DRGN82512
Интересно, а как с async \ await убрать потоки совсем? Внизу показывает 8. Слышал как-то можно кооперативную многозадачность через них организовать при использовании ExecutionContext и SynchronisationContext.
Ну понятно что по хорошему должны быть таймеры, но это наверное не наш путь. Хотя может наш.
И кстати с async лямбдой у меня что-то не получилось.
koodeer 06.01.2015 04:32 # 0
Смотрю что оно там показывает. Вероятно, Process.GetCurrentProcess().Threads.Coun t.
Минимум будет три потока. Плюс энное количество специальных: http://blogs.msdn.com/b/yunjin/archive/2005/07/05/435726.aspx
Убрать совсем, чтоб UI замёрз?
laMer007 06.01.2015 12:56 # 0
http://rextester.com/GODX99721
Ну а с другой стороны не факт, что это число потоков в пуле. Тогда сортировка совсем поломается.
laMer007 06.01.2015 13:21 # 0
http://rextester.com/SQIHB19182
Не знаю как тут C# творит чудеса
3.14159265 06.01.2015 13:34 # +1
koodeer 06.01.2015 23:06 # 0
Однако, читал где-то год назад на кывте один тред , где схлестнулись гуру c++ и дотнета, как раз по поводу async/await, так дотнетчики позорно слились (имхо).
Крестовики показали, что можно с любой функцией работать асинхронно, а в шарпике она должна быть специально для этого написана.
roman-kashitsyn 06.01.2015 23:28 # 0
В крестах дефолтный асинк либо порождает новый тред, либо выполняет функцию прямо в текущем потоке (зависит от опций и кол-ва живых тредов). При наличии нормального тредпула кресты в теории могут быть удобнее.
laMer007 07.01.2015 01:01 # 0
Да не может быть! Неужели макрософт это всеже смогла пропихнуть? Это в С++14? Или какое-то расширение в майкрософтском компиляторе?
laMer007 07.01.2015 01:12 # 0
А я попутал. Майкрософт свой чуда асинк пытался впихнуть в сишарповом смысле в стандарт 11. Слились. Линус послал всех лесом
laMer007 07.01.2015 03:05 # 0
и резьюмейбл йелд
koodeer 07.01.2015 03:09 # 0
Тред большой и там в разных подветках была битва.
laMer007 07.01.2015 12:16 # 0
Ищи ключевые слова, что я назвал:
http://meetingcpp.com/index.php/br/items/resumable-functions-async-and-await.html
laMer007 07.01.2015 13:03 # 0
async_code
await_async
И я что-то не понял где асинхронный кол и последующий авайт в произвольном месте кода? А то await_async не позволяет в произвольном месте кода произвести авейт
laMer007 07.01.2015 13:52 # 0
Других вариантов получить тот же функционал помоему нет
laMer007 07.01.2015 01:00 # 0
Ну так вызов обычной функции завернуть в асинк функцию и вот тебе проблема решена.
koodeer 07.01.2015 03:09 # 0
laMer007 07.01.2015 12:18 # 0
laMer007 07.01.2015 14:14 # 0
3.14159265 07.01.2015 01:44 # 0
Это потому что большинство дотнетчиков — тупые и ограниченные этим самым C#, кмк.
Хоть С++ и говно, но на ГК большая часть толковых пользователей промышляет именно крестоблядством.
Разгадка парадкоса мне видится в том что написание и понимание разных ебанутых крестокодов, а также непрерывная борьба с граблями неплохо развивает мышление и смекалку.
koodeer 07.01.2015 03:14 # 0
Вот только проблема в том, что плюсовики добираются до буста, корутин, асинхронности и т. п. лишь через несколько лет обучения.
В то время как в современном дотнетике сходу предлагается использовать async/await. Поэтому даже кодомакаки его используют.
bormand 07.01.2015 11:01 # +4
Благодаря чему они к этому морально готовы, а не бросаются пихать все это во все дыры.
LispGovno 08.01.2015 21:35 # 0
bormand 08.01.2015 21:44 # 0
Стойко перенося боль и унижения от boost::asio.
> ничего не умеешь
Нук, насоветуй чего-нибудь интересного на почитать (кроме бустовских либ, само собой).
LispGovno 08.01.2015 22:40 # +1
bormand 08.01.2015 22:44 # +2
TarasB от нас что-то скрывает....
> И последний работает тока в вин8
Это же развитие C++/CLI с фреймворком и сборкой мусора?
LispGovno 08.01.2015 23:00 # 0
тбб - это интел тбб. я хз. может даже платить надо. не качал
с++\сх для вин восемь - это как Swift для макоси.
привязка целого языка. личный вин рантайм на ком объектах с рефлексией (вин рт) вместо фреймворка. счетчики ссылок вместо гц. притом местный счетчик ссылок boost::intrusive_ptr встроен в язык как ^ вместо *.
roman-kashitsyn 08.01.2015 23:03 # 0
tbb - очень даже неплохая либа. Есть опен-сорсная версия либы, она присутствует в дебиановской репе с незапамятных времён.
Юзал из неё контейнеры, параллельные алгоритмы, pipeline.
laMer007 06.01.2015 13:37 # 0
http://rextester.com/SDYJI94409
Добавил элементов и отреверсил, чтобы наименьшие элементы были в конце листа. Получается или число потоков совпадает с числом элементов в листе или все происходит в одном или н потоках притом в каждом из них запланированно к событий одновременно (По сути потоки переиспользуются кооперативно).
Кстати сортировка очевидно работает на листах без random access
3.14159265 05.01.2015 22:20 # 0
sort(left)
sort(right)
Потому никаких хвостовых рекурсий там не будет, будет дерево 2-4-8-16.
roman-kashitsyn 05.01.2015 22:28 # 0
3.14159265 05.01.2015 22:29 # +1
laMer007 05.01.2015 22:33 # +1
3.14159265 05.01.2015 22:34 # +1
Поздравляю, еще чуть-чуть и вы изобретёте quantum bogosort.
bormand 06.01.2015 10:05 # +1
bormand 06.01.2015 10:39 # +2
3.14159265 06.01.2015 16:25 # +2
И сюрприз!, положить/достать из этой очереди 1 элемент можно за O(log(N)), а отсортировать надо N. Опять N*log(N)
laMer007 06.01.2015 13:08 # 0
1024-- 07.01.2015 11:34 # 0
laMer007 07.01.2015 12:23 # 0
ps: А гейдев не только говнокод пытается захватить, он ещё и на хабр свои щупальца протянул.
3.14159265 07.01.2015 14:50 # 0
Вроде в статье написано:
Сортировка слияниями на месте (in-place merge sort) укладывается в ограничения 1 и 2 (есть даже ее stable вариант, но там жесть), но совершенно непонятно, как ее эффективно реализовать без произвольного доступа к памяти.
laMer007 07.01.2015 15:00 # 0
А зачем он? Он и не нужен, когда список сортируешь.
3.14159265 07.01.2015 15:11 # 0
я тоже не совсем понимаю как этот инплейс (то есть на том же списке) мердж сорт будет сливать последние блоки данных, сравнивая их начала. Для этого ему надо будет постоянно бегать в средину списка.
> Он и не нужен, когда список сортируешь.
Любой произвольный доступ по индексу можно заменить последовательной итерацией N элементов.
В первом случае мы получаем элемент за O(1), во втором за O(N).
laMer007 07.01.2015 15:31 # 0
поблочно копируешь из листа в вектор длиной к
юзаешь любую сортировку на блоке.
сливаешь обратно в лист
ну а вообще в типичном квик сорте стек тоже юзается, так что там О(log n) на память внезапно.
bormand 07.01.2015 16:35 # 0
И тут мы подходим к вопросу - а так ли нужно это O(1) по памяти? Ведь их квиксорт с медианой гарантированно укладывается в O(log(N)) памяти, и для всех разумных применений это жалкие 32 слота, которые можно считать константой...
laMer007 07.01.2015 17:35 # 0
32 байта хватит всем
TarasB 07.01.2015 18:39 # 0
TarasB 07.01.2015 18:57 # 0
bormand 07.01.2015 19:53 # 0
Блоки с размером по степеням двойки поди? Забыл как называется этот метод ;(
TarasB 07.01.2015 19:55 # 0
bormand 07.01.2015 19:58 # 0
Почему? Там же вроде свободные половинки приклеивались друг к другу? Или ради O(1) этой поклейкой пришлось пожертвовать?
TarasB 07.01.2015 20:12 # 0
http://www.gamedev.ru/flame/forum/?id=196218
(не с 1 страницы)
bormand 07.01.2015 20:26 # +1
TarasB 07.01.2015 21:01 # 0
тупо да?
единственное что я допилил чуток освобождение последних пустых блоков
3.14159265 07.01.2015 21:41 # 0
same shit
TarasB 07.01.2015 22:28 # 0
А ещё я настолько ебанулся на алгоритмической сложности, что вместо вектора с его ужасными реаллокациями запилил треугольный буфер - это массив из указателей на блоки элементов, в первых двух блоках по 16 элементов, в каждом следующем вдвое больше, блоки заполняются последовательно. Все операции по сложности как у вектора, только константа в 10 раз больше XD, зато вставка нового элемента гарантированно (а не амортизированно) О(1).
laMer007 07.01.2015 23:36 # 0
TarasB 07.01.2015 23:49 # 0
у него O(1) гарантия на вставку в конец?
вы блин идеи знакомые услышали, ближайшее слово по смыслу нашли и типа опа оно
Soul_re@ver 08.01.2015 03:09 # 0
O(k) в худшем случае. k конфигурируемо при компиляции (размер сегмента). Так что да, O(1), меняется только размер константы.
TarasB 08.01.2015 15:14 # 0
3.14159265 08.01.2015 00:08 # 0
Тю, я где-то похожее видел.
И тоже пилил свой, но у меня проще: буфер прирастает блоками константного размера. Адресация — сегмент+смещение.
Стандартный java arrayList — по мне говно. Плюс когда удаляем элементы (с концов) вектор составленный из страниц сдувается, а стандартный — хуй, вроде как-то руками можно шринкать, но это говнятина.
>зато вставка нового элемента гарантированно (а не амортизированно) О(1).
Тоже так получается.
Где-то у классиков (Кнут вроде цитату приводил) видел мысль: о экспоненциальной сложности надо думать, только когда имеешь экспоненциальные объемы данных.
TarasB 08.01.2015 00:12 # 0
У меня-то 28 блоков хватит на миллиард, и я 28 указателей на блоки храню статически.
А причём тут экспоненциальная сложность?
3.14159265 08.01.2015 04:27 # 0
Я думал над иерархической структуров из блоков. Типа rope, но обломался писать.
>А причём тут экспоненциальная сложность?
При том что для практических целей задрачивать сложность не особо и следует, т.к. у нас немного данных.
Гораздо большее значение и вес имеет константа. В типичных случаях O(N/64) может оказаться быстрее чем O(>9000)
bormand 08.01.2015 08:32 # 0
Тогда потеряем O(1) и довольно низкую константу на произвольном доступе...
bormand 08.01.2015 10:24 # 0
3.14159265 08.01.2015 15:27 # 0
Я тоже так подумал.
> Хотя, если мы возьмем достаточно большие блоки (4096 байт например) - трёх уровней хватит за глаза.
Ну я думал что число уровней будет расти по мере роста структуры.
То есть <64 - один уровень - линейная адресация.
<64*64=4096 два уровня - сегмент+смещение
>4096*64=256К
Три уровня
>4M
4 уровня
>256M
5 уровней.
Но это сложно. Мне больше нравится идея (опять-таки ничего нового я не предлагаю) динамического размера страницы, как в процессорах: можно выбрать 4К, можно 4М. И просто 2 уровня: сегмент+смещение.
А там и память кончится. Реально на практике очередей больше 1 миллиарда не встречал, а списки/векторы и того меньше (обычно их потолок - десятки тысяч).
bormand 08.01.2015 15:42 # 0
Но ведь это ужасная переголова в момент переключения размера страниц. Или просто выбираем такой размер страницы, которого для нашей задачи будет достаточно?
3.14159265 08.01.2015 18:13 # 0
Ну в процессоре так и делают. Что мешает сделать нам программно?
К сожалению софт так просто не может выбрать размер страницы, с которой он запущен (чтобы ускорить адресацию на уровне ЦПУ).
Но вот 7max может запускать приложения в отдельном адресном пространстве со страницами 4Mb, в то время как ОС работает со стандратными маленькими 4Kb.
То есть фактически в рамках одной оси могут сосуществовать приложения с разным размером страниц.
Более того в последних процах сделали монструозные 1Gb страницы.
3.14159265 08.01.2015 18:24 # +1
roman-kashitsyn 08.01.2015 01:09 # 0
Это и есть std::deque, упомянутая выше
bormand 07.01.2015 20:02 # 0
3.14159265 07.01.2015 21:42 # 0
>сливаешь обратно в лист
к - константа, верно понимаю?
Как тогда смерджить джва блока, которые больше чем к?
TarasB 07.01.2015 22:29 # +1
3.14159265 08.01.2015 00:03 # 0
Ну хорошо у тебя есть джва отсортированных блока размером ка, что дальше? N» к
TarasB 08.01.2015 00:11 # 0
алгоритмическая сложность зависит от ка
очевидно, что если ка равно 1, то имеем сортировку вставками, тоисть квадрат по сложности
3.14159265 07.01.2015 14:58 # 0
>да, по сути все идеи данной статьи не мои — я просто разместил объяву
Типичный хабр, в принципе я схватил идею сразу, я и раньше много думал/читал как оптимальнее найти медиану для квиксорта.
В целом статья неплохая, но есть сомнения что сложность O(log(N)*N) (с учётом связности списка обмен и перемещения джвух произвольных элементов - O(N))
TarasB 07.01.2015 18:33 # 0
для двусвязного и так сам понимаешь
TarasB 07.01.2015 18:32 # 0
> забанен
начало очень в стиле
LispGovno 08.01.2015 02:37 # +1