Здравствуйте, Jolly Roger, Вы писали:
R>>Кстати возможностью отслеживания смерти потоков под мьютексом пользуются очень редко, т.к. что бы это имело смысл алгоритм внутри критической секции должен быть полностью lock-free, т.е. теоретически lock-free.
JR>Так ведь и смерть потока внутри мьютекса — событие экстраординарное, я даже сначала не хотел его упоминать Зато захват низкоприоритетным потоком вполне реален, а в этом случае система помогает, она разбудит такого захватчика, если тот-же мьютекс потребуется более высокоприоритетному потоку.
Если речь о потоках, то экстраординарное. А если речь о процессах, общающихся через разделяемую память, то вполне нормальное.
Если имеются потоки разного приоритета, то необходимо использовать полностью lock-free или wait-free алгоритмы, они иммуны к инверсиям приоритетов, смерти потоков и т.д. Благо такие алгоритмы есть.
S>> long read = InterlockedIncrement(&m_reading) % m_size;
S>> *target = m_buffer[read].data; //если тут произойдёт исключение, то колл. читателей будет неверно.
S>> m_buffer[read].status = cell_Read;
S>> finalize_read();
S>>
C>Ура! C>Наконец кто-то обратил внимание на это C>Это легко решаемая проблема, весь необходимый finalize переносится в деструктор спецыального класса, добавляется ещё один флажок: cell_Broken C>и всё работает как часы. однако такой код становится неудобо читаемым, и тут его анализировать(в виртуальной машине класса мозг) будет сложнее. Поэтому перед выкладкой я убрал весь код обработки ошибок.
Согласен.
Кстати, такой алгоритм используется в библиотеке Intel TBB, класс tbb::concurrent_queue. Там можно поглядеть детали реализации.
Хотя с исключением во время потребления элемента не так просто справится, т.к. поток уже сдвинул позицию для потребления, и что потом делать с этим "подвисшим" элементом не понятно.
В целом, я бы просто сказал, что копирование не должно кидать, для надёжности можно добавить проверку на __has_nothrow_assign/__has_nothrow_copy.
Здравствуйте, remark, Вы писали:
R>Скоро я тут покажу как это сделать для очереди на основе фиксированного буфера — один _InterlockedCompareExchange() на операцию. Спин-мьютекс не может быть быстрее, т.к. он подразумевает как минимум один _InterlockedCompareExchange().
Здравствуйте, Caracrist, Вы писали:
C>Довёл до ума (если кто хочет посмотреть на это чудо, пишите ) C>После тестов с конечной версией, Interlocked быстрее в целом, в начале не значительно, но чем больше потоков тем больше разница. При 150+ потоках уже на порядки быстрее. Однако, есть ещё одно неприятное свойство: Interlocked вешает всю систему(win7 i7х64 4 x hyperthreading). Процессоры занимаются инвалидацией вместо выполнений других команд. Окна почти по пикселям рисуются.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Caracrist, Вы писали:
C>>Довёл до ума (если кто хочет посмотреть на это чудо, пишите ) C>>После тестов с конечной версией, Interlocked быстрее в целом, в начале не значительно, но чем больше потоков тем больше разница. При 150+ потоках уже на порядки быстрее. Однако, есть ещё одно неприятное свойство: Interlocked вешает всю систему(win7 i7х64 4 x hyperthreading). Процессоры занимаются инвалидацией вместо выполнений других команд. Окна почти по пикселям рисуются.
R>Попробуй протестировать на том же тесте вот эту — будет интересно услышать результаты: R>http://www.rsdn.ru/forum/cpp/3730905.1.aspx
Ведёт себя точно также как и мой, нереально ускоряется при очень большом количестве потоков, тоже вешает систему,
но работает в полтора/два раза быстрее моего. Хорошее решение если будет ответ на http://www.rsdn.ru/forum/src/3731081.1.aspx
Здравствуйте, Caracrist, Вы писали:
C> C>Ведёт себя точно также как и мой, нереально ускоряется при очень большом количестве потоков, тоже вешает систему, C>но работает в полтора/два раза быстрее моего. Хорошее решение если будет ответ на http://www.rsdn.ru/forum/src/3731081.1.aspx
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Caracrist, Вы писали:
C>> C>>Ведёт себя точно также как и мой, нереально ускоряется при очень большом количестве потоков, тоже вешает систему, C>>но работает в полтора/два раза быстрее моего. Хорошее решение если будет ответ на http://www.rsdn.ru/forum/src/3731081.1.aspx
других проблем пока не вижу. Кстати, хотел сделать подобное, но не смог придумать, что делать в упомянутом случае.
R>А что за тест и железо, если они работают почти одинаково?
Здравствуйте, Caracrist, Вы писали:
C>Здравствуйте, remark, Вы писали:
R>>Здравствуйте, Caracrist, Вы писали:
C>>> C>>>Ведёт себя точно также как и мой, нереально ускоряется при очень большом количестве потоков, тоже вешает систему, C>>>но работает в полтора/два раза быстрее моего. Хорошее решение если будет ответ на http://www.rsdn.ru/forum/src/3731081.1.aspx
других проблем пока не вижу. Кстати, хотел сделать подобное, но не смог придумать, что делать в упомянутом случае.
R>>А что за тест и железо, если они работают почти одинаково?
C>i7 2.66GHz 4xCore HyperThreading C>win7x64 C>32bit threads C>Visual Studio 2008 (release)
64bit threads Такой же результат:
BUFFER_TYPE 0:
Starting with 8 sender threads and 8 reciever threads
Buffer size: 1024
Sending 6400000 messages
Sent in 3855637416 milliseconds, 1.65991e+006mps
Sent in 3590368002 milliseconds, 1.78255e+006mps
Sent in 3631132264 milliseconds, 1.76254e+006mps
Sent in 3703565077 milliseconds, 1.72806e+006mps
Sent in 3966326413 milliseconds, 1.61358e+006mps
Sent in 3785466758 milliseconds, 1.69068e+006mps
Sent in 3723342145 milliseconds, 1.71889e+006mps
Sent in 4017820926 milliseconds, 1.5929e+006mps
Sent in 3811305657 milliseconds, 1.67921e+006mps
Sent in 3776062056 milliseconds, 1.69489e+006mps
Average speed: 1.69232e+006mps
BUFFER_TYPE 1:
Starting with 8 sender threads and 8 reciever threads
Buffer size: 1024
Sending 6400000 messages
Sent in 3206550233 milliseconds, 1.99591e+006mps
Sent in 3236804837 milliseconds, 1.97726e+006mps
Sent in 3235771104 milliseconds, 1.97789e+006mps
Sent in 3181427611 milliseconds, 2.01168e+006mps
Sent in 3203853852 milliseconds, 1.99759e+006mps
Sent in 3168177450 milliseconds, 2.02009e+006mps
Sent in 3238192411 milliseconds, 1.97641e+006mps
Sent in 3234528728 milliseconds, 1.97865e+006mps
Sent in 3225094310 milliseconds, 1.98444e+006mps
Sent in 3226326709 milliseconds, 1.98368e+006mps
Average speed: 1.99036e+006mps
BUFFER_TYPE 2:
Starting with 8 sender threads and 8 reciever threads
Buffer size: 1024
Sending 6400000 messages
Sent in 2533942931 milliseconds, 2.52571e+006mps
Sent in 2472673173 milliseconds, 2.58829e+006mps
Sent in 2111953419 milliseconds, 3.03037e+006mps
Sent in 2482179117 milliseconds, 2.57838e+006mps
Sent in 2460225930 milliseconds, 2.60139e+006mps
Sent in 2360783846 milliseconds, 2.71096e+006mps
Sent in 2419441588 milliseconds, 2.64524e+006mps
Sent in 2361790763 milliseconds, 2.70981e+006mps
Sent in 2386956468 milliseconds, 2.68124e+006mps
Sent in 2346342869 milliseconds, 2.72765e+006mps
Average speed: 2.6799e+006mps
BUFFER_TYPE 0:
Starting with 80 sender threads and 80 reciever threads
Buffer size: 1024
Sending 640000000 messages
Sent in 120578 milliseconds, 5.30777e+012mps
Sent in 77520 milliseconds, 8.25593e+012mps
Sent in 82910 milliseconds, 7.71921e+012mps
Sent in 75049 milliseconds, 8.52776e+012mps
Sent in 90059 milliseconds, 7.10645e+012mps
Sent in 115923 milliseconds, 5.52091e+012mps
Sent in 171828 milliseconds, 3.72465e+012mps
Sent in 268397 milliseconds, 2.38453e+012mps
Sent in 171268 milliseconds, 3.73683e+012mps
Sent in 303200 milliseconds, 2.11082e+012mps
Average speed: 5.43949e+012mps
BUFFER_TYPE 1:
Starting with 80 sender threads and 80 reciever threads
Buffer size: 1024
Sending 640000000 messages
Sent in 143314 milliseconds, 4.46572e+012mps
Sent in 113635 milliseconds, 5.63207e+012mps
Sent in 118024 milliseconds, 5.42263e+012mps
Sent in 160056 milliseconds, 3.9986e+012mps
Sent in 142089 milliseconds, 4.50422e+012mps
Sent in 149221 milliseconds, 4.28894e+012mps
Sent in 5081233 milliseconds, 1.25954e+011mps
Sent in 164228 milliseconds, 3.89702e+012mps
Sent in 157656 milliseconds, 4.05947e+012mps
Sent in 127153 milliseconds, 5.03331e+012mps
Average speed: 4.14279e+012mps
BUFFER_TYPE 2:
Starting with 80 sender threads and 80 reciever threads
Buffer size: 1024
Sending 640000000 messages
Sent in 107283 milliseconds, 5.96553e+012mps
Sent in 65079 milliseconds, 9.8342e+012mps
Sent in 49538 milliseconds, 1.29194e+013mps
Sent in 68178 milliseconds, 9.38719e+012mps
Sent in 53686 milliseconds, 1.19212e+013mps
Sent in 96981 milliseconds, 6.59923e+012mps
Sent in 59298 milliseconds, 1.07929e+013mps
Sent in 135170 milliseconds, 4.73478e+012mps
Sent in 150741 milliseconds, 4.24569e+012mps
Sent in 123354 milliseconds, 5.18832e+012mps
Average speed: 8.15884e+012mps
Здравствуйте, Caracrist, Вы писали:
C>>>> C>>>>Ведёт себя точно также как и мой, нереально ускоряется при очень большом количестве потоков, тоже вешает систему, C>>>>но работает в полтора/два раза быстрее моего. Хорошее решение если будет ответ на http://www.rsdn.ru/forum/src/3731081.1.aspx
других проблем пока не вижу. Кстати, хотел сделать подобное, но не смог придумать, что делать в упомянутом случае.
R>>>А что за тест и железо, если они работают почти одинаково?
У тебя что-то не так в тесте. Не может моя очередь потреблять 1730 тактов на операцию. У меня она ~40-90. С поправкой на HT это будет ~50-180.
100000 операций на поток это маловато. Моя очередь может это обработать за 2мс, а это сравнимо со стоимостью запуска/завершения потока, т.е. получается, что ты стоимость удвоил.
Я затрудняюсь трактовать: C>Average speed: 1.69232e+006mps C>Average speed: 5.43949e+012mps
Почему скорость выросла в 1000000 раз?