- 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
double[,] ThreadMatrixMult(int size, double[,] m1, double[,] m2)
{
double[,] result = new double[size, size];
var threads = new List<Thread>(size);
for (int i = 0; i < size; i++)
{
var t = new Thread( ti =>
{
int ii = (int)ti;
for (int j = 0; j < size; j++)
{
result[ii, j] = 0;
for (int k = 0; k < size; k++)
{
result[ii, j] += m1[ii, k] * m2[k, j];
}
}
});
threads.Add(t);
t.Start(i);
}
foreach (Thread thread in threads)
thread.Join();
return result;
}
Хотя можно переписать на Эрланге, чё. Там создание и уничтожение потоков - дешевая операция.
Зато сложение и умножение - недешевая. Вроде тут на ГК писали что он в сотни раз дольше матрицы умножает, чем сишный код.
Ну серьезно, без смайликов и зеленого юмор уже непонятен?
>t.Start(i);
>thread.Join();
Вот тебе бабушка и AssParallel.
Не верю что в шарп до сих пор не завезли нормальные тредпулы c work stealing.
Они же исполняются на том самом тредпуле. Не?
http://govnokod.ru/17421#comment262107
std::make_exception
std::current_exception
О деталях я как-то не думал, но подозреваю, что там больше одного копирования (при выбрасывании) и не происходит, а исключения изначально живут в памяти, доступной всем потокам.
Меня вот это смущает: holding a reference to the exception object, or a copy of the exception object, it is implementation-defined if a copy is made. Передача потенциальной ссылки в соседний поток как-то подозрительно смотрится...
Похоже на то. Адреса не стековые, когда исключение ловишь. Походу throw их куда-то заныкивает, пока тип еще известен.
P.S. Т.е. throw само по себе может кинуть bad_alloc вместо нужного исключения?
Может, конечно, если исключение аллоцирует много памяти.
Думаю, std::exception::what() возвращает const char* вместо std::string не просто так :)
Не исключено, что сами исключения могут аллоцироваться в отдельном резервном участке памяти (иначе как кинуть bad_alloc?), но это только догадки.
Заранее создать один экземпляр std::bad_alloс на чорный день. Его можно даже не пересоздавать, а всегда возвращать один и тот же. Он всё равно иммутабельный, и никто его не испортит.
Вот это бесит, кстати. Из-за этого нельзя построить этот what() на лету.
Короче promise асинхронный стандартный. В js такого море.
Говорят что он хорош когда много мелких заданий.
http://literatejava.com/threading/fork-join-parallelization-feature-or-problem/
http://stackoverflow.com/questions/8206318/is-javas-fork-and-join-thread-pool-is-good-for-executing-io-bound-task
Проблема в оверхеде: work-stealing causes high contention
Очередь тут не выступает бутылочным горлышком.
Но допустим у нас 64 ядра. А задачи мелкие и быстро исполняются (микросекунды, сопоставимо со временем захвата лочки), то нам надо очень быстро накладывать задачи (желательно тоже в несколько потоков), и быстро их забирать. В случае рекурсивных заданий потоки сами же и ложат задания в очередь.
И тогда грубо говоря 32 потока ждут чтобы положить, и 32 ждут чтобы взять. И все они борются за право поменять одну и ту же область памяти (счётчик или указатель). И наступает пиздец...
В многопоточном кодинге важно чтобы не было бутылочных горлышек в виде мест, где расспаралелить нельзя (закон Амдала). Очередь это и есть такое место. Просто на типичных задачах при количествах ядер 4,8 это еще не было заметно.
Логичным и простым решением кажется сделать 64 очереди у 64 потоков.
А теперь советую подумать, как организовать точку входа, так, чтобы она раскладывала задания между очередями и не создавала contention?
раунд робин
У лентяев много накопится, остальным делать нефиг будет.
Поэтому переходим к следующему логичному вопросу (который поцчему-то многие часто игнорируют)
Как сделать атомик счётчик чтоб 64 потока при его инкременте не соревновались за один и тот же участок памяти?
Переместив контеншн в аллокатор, лол.
да никак они не возвращаются. тупо один поток из тредпула извлекли он реально занят на ожидании события. лажа вообщем тупое просирание процессорного времени, системных ресурсов и мегабайта под стек, что в высоконагруженных серверах жопа
Проблема обычных пулов в том что они строятся на очереди, а очередь по сути двухпоточная (одна лочка или CAS на put, другая на take), и выше она не масштабируется.
Вот надо придумать какую-то концепцию чтоб можно было добавлять задачи с N потоков и раскладывать их же по M исполнителям.
То есть если брать очереди, то желательно иметь их M штук чтоб contentionа не было и оно параллелилось. Но как их координировать?
Вот кто-то сел и подумал что есть рекурсивные задачи, которые внутри себя содержат другие задачи, итд, если их спаунить в локальной очереди, то contention сильно уменьшится. А координацию сделал через скан чужих очередей (пока чужой поток занят делом). Понятно что это порождает некий оверхед.
В случае IO задачи просто не успевают исполняться так быстро, что потоки не успевают накладывать новые, то есть очередь НЕ становится бутылочным горлышком. Потому work-stealing не очень-то и нужен.
Есть другой менее известный паттерн называется Disruptor. Там всё еще круче, правда IO он совсем не любит.
Изложение немного сбойное и косноязычное, поскольку я устал, но надеюсь мысль зачем это всё городится понятна.
честно говоря - нет. по моему вы просто страдаете фигней.
потоки и скедулинг были и будут оставатся относительно дорогими. потому что скедулинг был и все еще остается в сердце экспоненциальным алгоритмом - сколько бы на него O(1) помады не красили.
если у вас lock contention на очереди задач становится проблемой, то это однозначная индикация что у вас задачи слишком мелкие.
другими словами: если вы будете всякой мелкой херней спамить хардварные ресурсы (проц тоже железо!) то у вас никогда ничего скалироватся не будет.
Цена: 9900 р.
Размер: 29 х 34 х 9 см
Материалы: Медь, Бархат, Дерево ® <a href=https://vipcu.ru/category/derevyannye-klyuchnitsy/>такой</a>
<a href=https://vipcu.ru/derevyannaya-klyuchnitsa-tt-s-nagradami-sssr-16-276/><img>https://vipcu.ru/wa-data/public/shop/products/48/25/2548/images/4429/4429.200x0.jpg</img></a> <a href=https://vipcu.ru/derevyannaya-klyuchnitsa-nastennaya-denezhnoe-derevo/><img>https://vipcu.ru/wa-data/public/shop/products/58/08/858/images/4813/4813.200x0.jpg</img></a> <a href=https://vipcu.ru/derevyannaya-klyuchnitsa-podkova-s-zolocheniem-14-150/><img>https://vipcu.ru/wa-data/public/shop/products/43/25/2543/images/4404/4404.200x0.jpg</img></a>