> > Смотря какая природа у этого варианта. У меня сейчас два потока
> > работают
> > - один грузит данные из базы
> > - второй эти данные обрабатывает.
>
> В идеале первый поток не нужен.

Странные у тебя идеалы :)

>   Я бы сделал работу следующим образом: поток-читатель считывает из базы
> блок данных и передаёт его на обработку второму потоку через
> PostThreadMessage (по старинке) или QueueUserAPC (по современному).
> Размер блока данных подбирается чтобы его обработка занимала примерно
> полсекунды.

Я это сделал через "буфер обмена", защищенным критческой секцией.

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

Он у меня приостанавливается :)

У меня даже фоновый поток выгрузки модифицированных страниц может
завершаться, когда у него нет работы. Правда, работой его по самую
макушку заваливают.

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

Иногда "буфер" все таки опустошается. Это когда сервер начинает
чухаться с подгрузкой нужной части данных в свой кэш.

-------

Вообщем, текущее положение дел с "машиной тьюринга" такое.

- Я прикрутил фоновый поток выгрузки модифицированных страниц.

- Послушал как работает машина (в натуре на слух), и понял - нужно
нафиг отключить буферизацию файловых операций. То бишь указал флаги
FILE_FLAG_WRITE_THROUGH, FILE_FLAG_NO_BUFFERING

- Это потребовало заюзать память, выделяемую через VirtualAlloc. Типа,
как завещал Великий LOA :)

- Гудение винтов стало равномерным :) (кстати пару раз слышал странные
щелчки)

- Посмотрев на это дело, я понял что бежать больше некуда и надо
доделывать менеджер кэша - в него писать не через read/write функции,
а напрямую. И переделать управление хеш-таблицей - отказаться от
мелких блоков, а перейти к блокам занимающим всю страницу целиком.
Продолбенился над реализацией целый день. Получилось красиво.

И - о чудо! У меня многопоточная реализация стала работать вровень с
однопоточной. Более того - может это меня заглючило (в 3 часа ночи) -
даже немного быстрее. Вообщем, системные затраты стали очень
маленькими и диспетчер задач светился радостным зеленым цветом.

Одним из забавных моментов была при обработке какой-то порции данных,
когда общая нагрузка на процессор (HT включен) плавно поднималась с 50
до 100, там держалась, а потом плавно опускалась. Возможно это связано
с увеличением числа попаданий в локальные кэши каждого потока. Хотя по
правде - шайтан его знает, с чем это связано.

----------
Но, плят, щастье длится ровно столько сколько заполняется кэш.

Напомню, мне нужно построить уникальный индекс для (по последним
прогнозам) 100 лимонов элементов вида (ID1, ID2). Максимум что я смог
осилить - 20 лимонов.

Сейчас, для построения индекса элементов, юзаю хеш-таблицу. По формуле
(ID1+ID2)/HashTableSize определяю элемент таблицы. В элементе хранится
указатель на упорядоченный блочный список. Блок списка равен размеру
страницы (4K).

Фоновый поток выгружает самые старые модифицированные страницы. Но,
судя по индикации счетчиков размеров списков "чистых" и "грязных"
страниц, в эти "очищенные" страницы сразу же срут и они возвращаются в
очередь "грязных" страниц.

Скорость генерации очень высокая - программа только начинает работать,
а уже сразу выжирает под 30-40 тысяч страниц. И дальше очень
интенсивно гадит в каждую из них.

После заполнения кэша (я эксперементирую с кэшем на 120 тыс четырех
килобайтных страниц) производительность падает до копеечных размеров.
Я пробовал останавливать потоки генерации, что бы дать "выгружателю"
сбросить все на диск - эффект мизерный. После того как "генераторы"
возобновляют работу - производительность не повышается и очередь
грязных страниц неулонно растет. Это зарезало мою идею уменьшать
приоритет генераторов при катастрофическом загрязнении кэша.

Пробовал играть и с размером страниц и c HashTableSize - общая картина
не улучшается.

----------
Мне кажется что проблема все таки в самой hash-таблице. Точнее в
стоимости добавления нового элемента в существующий список. Если
программа способна генерировать свыше 20 тыс уникальных комбинаций в
секунду, и каждая из них попадает в свой список хеш-таблицы, то тут
ничего не спасет. Я же, блин, постарался - отсортированность
поддерживаю. Так что тут еще и уже заполненные блоки списков могут
модифицироваться...

Сейчас буду прикладывать к голове умную книжку с описанием конструкции
Б-деревьев.

----------
Не, но многоточность я таки победил. Честное пионерское :)

... Как сложно делать простые вещи. И какими сложными они потом
оказываюся :(

Коваленко Дмитрий.

Ответить