c# фоновая многопоточность
От: Tbr  
Дата: 30.06.10 07:11
Оценка:
Есть готовая программа на C#, которая отлично делает с пару десятков разных вычислений, допустим Фибоначчи, Хибоначчи, Цибоначчи...
На форме есть кнопки, которые так и называются: Фибоначчи, Хибоначчи...

При нажатии на кнопку, запускается соответствующий просчет и результаты каждые 1/5 сек выводятся на форму, при нажатии на другую кнопку расчет прерывается и начинают выводиться результаты другой функции. Каждая из функций использует многопоточность и всё это вместе работает шикарно...на 4-ядерном процессоре. Стоит уменьшить количество доступных ядер до 1-2, программа начинает жестко тупить.

Реализация:
кнопка на форме вызывает backgroundWorker, который подготавливает данные и запускает одну из многопоточных функций

//многопоточная функция
double rezultat;//постоянно изменяется в функции fun, а каждые 1/5 сек отсюда выводится на форму
void fun(BackgroundWorker worker){}
void fibonacci(BackgroundWorker worker)
{
...
threads=48;
funcDelegate deleg = new funcDelegate (func);
IAsyncResult[] results2 = new IAsyncResult[threads];
for (int i = 0; i < threads; i++)//цикл перебора всех комбинаций
   results2[i] = deleg .BeginInvoke(worker);

for (int i = 0; i < threads; i++)//получение результатов
   d.EndInvoke(results2[i]);
}


1. Если убрать многопоточность, то все работает шикарно на любом количестве ядер.
2. Если запускать вычисление не в фоне, а результат получать по завершении работы функции то всё так же работает шикарно.
3. Если добавить кнопку "СТОП" и прерывать предыдущее вычисление кнопкой, а потом начинать следующее, то так же всё работает.
4. Если на компьютере 4 ядра, то тоже все прекрасно.

Уже всё перечитал, и про пулы потоков тоже, всё испытал, до чего мозгов хватило.
Посоветуйте, как правильно реализовать.
Re: c# фоновая многопоточность
От: andrey82  
Дата: 30.06.10 07:18
Оценка:
Здравствуйте, Tbr, Вы писали:


Tbr>1. Если убрать многопоточность, то все работает шикарно на любом количестве ядер.

...
Tbr>4. Если на компьютере 4 ядра, то тоже все прекрасно.

Вообще-то запускать большое количество (больше, чем ядер в системе) потоков с вычислениями смысла не имеет. Быстрее расчет не выполнится, а будут только лишние накладные расходы на переключения между потоками и т.п.
Если все-таки надо вести несколько расчетов параллельно — то стоит нарезать исх. задание на небольшие порции и последовательно их выполнять.
Re[2]: c# фоновая многопоточность
От: Tbr  
Дата: 30.06.10 07:25
Оценка:
Здравствуйте, andrey82, Вы писали:

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



Tbr>>1. Если убрать многопоточность, то все работает шикарно на любом количестве ядер.

A>...
Tbr>>4. Если на компьютере 4 ядра, то тоже все прекрасно.

A>Вообще-то запускать большое количество (больше, чем ядер в системе) потоков с вычислениями смысла не имеет. Быстрее расчет не выполнится, а будут только лишние накладные расходы на переключения между потоками и т.п.


А сколько потоков запускать, чтобы работало и на планшете с Atom и на 4*OpteronX12?

A>Если все-таки надо вести несколько расчетов параллельно — то стоит нарезать исх. задание на небольшие порции и последовательно их выполнять.


Задание философское и невыполнимое, одна кнопка начинает показывать, как горит огонь, другая, как течет вода. Надо параллельно вычислять и выводить на форму и иметь возможность выбирать новое задание 5 раз в секунду.
Re: c# фоновая многопоточность
От: Tbr  
Дата: 30.06.10 08:25
Оценка:
Еще сразу же спрошу:

Я через диспетчер задач задаю соответствия, разрешаю программе пользоваться только одним ядром.
А может быть она думает, что ядра 4 и потому пытается запускать 4 потока одновременно, чем и вызывает дикие тормоза, а на реальном 1-ядерном процессоре всё будет работать?
Re: c# фоновая многопоточность
От: Mystic Украина http://mystic2000.newmail.ru
Дата: 30.06.10 08:41
Оценка:
Здравствуйте, Tbr, Вы писали:

Tbr>При нажатии на кнопку, запускается соответствующий просчет и результаты каждые 1/5 сек выводятся на форму, при нажатии на другую кнопку расчет прерывается и начинают выводиться результаты другой функции. Каждая из функций использует многопоточность и всё это вместе работает шикарно...на 4-ядерном процессоре. Стоит уменьшить количество доступных ядер до 1-2, программа начинает жестко тупить.


SetThreadPriority?
Re[2]: c# фоновая многопоточность
От: Tbr  
Дата: 30.06.10 09:03
Оценка:
Здравствуйте, Mystic, Вы писали:

M>SetThreadPriority?


Всё это не то, я разобрался с проблемой. Это косяк фреймворка.
Если в диспетчере задач уменьшаешь количество ядер для программы, фреймворк сильно тупит, видит, что прога загружает проц далеко не на 100% и начинает запускать еще потоки, причем если отключишь 3 ядра, то будет накидываться за раз по 3 потока, а через 10 секунд приложение превратится в 20-поточное (с отключенными то ядрами), причем все потоки будут работать одновременно. Это вызывает дикие тормоза и глюки.

Сейчас доделаю исходник, демонстрирующий это, выложу его и можно тему закрывать.
Re[3]: c# фоновая многопоточность
От: Pavel Dvorkin Россия  
Дата: 30.06.10 11:21
Оценка:
Здравствуйте, Tbr, Вы писали:

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


M>>SetThreadPriority?


Tbr>Всё это не то, я разобрался с проблемой. Это косяк фреймворка.

Tbr>Если в диспетчере задач уменьшаешь количество ядер для программы, фреймворк сильно тупит, видит, что прога загружает проц далеко не на 100% и начинает запускать еще потоки, причем если отключишь 3 ядра, то будет накидываться за раз по 3 потока, а через 10 секунд приложение превратится в 20-поточное (с отключенными то ядрами), причем все потоки будут работать одновременно. Это вызывает дикие тормоза и глюки.

Убери пул потоков, создавай потоки сам и никто не будет заводить новые потоки без твоего участия. Надеюсь.
With best regards
Pavel Dvorkin
Re: c# фоновая многопоточность
От: IT Россия linq2db.com
Дата: 01.07.10 00:14
Оценка:
Здравствуйте, Tbr, Вы писали:

Tbr>Уже всё перечитал, и про пулы потоков тоже, всё испытал, до чего мозгов хватило.

Tbr>Посоветуйте, как правильно реализовать.

Какой приоритет у рабочих потоков?
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: c# фоновая многопоточность
От: Tbr  
Дата: 02.07.10 09:55
Оценка:
Здравствуйте, IT, Вы писали:

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


Tbr>>Уже всё перечитал, и про пулы потоков тоже, всё испытал, до чего мозгов хватило.

Tbr>>Посоветуйте, как правильно реализовать.

IT>Какой приоритет у рабочих потоков?


Приоритет не выставлял, потому, как итак все работает. Правда эффективность 230-270% на 4-ядернике по сравнению с однопоточным.

Просто через пул потоков вызываю Environment.ProcessorCount штук и всё. Проц загружен на 100% и ничего не тормозит, не знаю, зачем нужен приоритет. А вот как эффективность поднять не понимаю.
Re[3]: c# фоновая многопоточность
От: Jolly Roger  
Дата: 02.07.10 12:20
Оценка:
Здравствуйте, Tbr, Вы писали:

Попробуйте ThreadPool.SetMaxThreads, и вообще с настройками пула поэкпериментируйте. А вообще описанное Вами похоже на баг, попробуйте отправить репорт.
"Нормальные герои всегда идут в обход!"
Re[3]: c# фоновая многопоточность
От: IT Россия linq2db.com
Дата: 02.07.10 14:44
Оценка:
Здравствуйте, Tbr, Вы писали:

IT>>Какой приоритет у рабочих потоков?

Tbr>Приоритет не выставлял, потому, как итак все работает. Правда эффективность 230-270% на 4-ядернике по сравнению с однопоточным.

Я бы посмотрел какой у этих потоков приоритет. Если такой же как у основного, то тогда тормоза вполне объяснимы.
Если нам не помогут, то мы тоже никого не пощадим.
Re[4]: c# фоновая многопоточность
От: Tbr  
Дата: 03.07.10 07:38
Оценка:
Здравствуйте, IT, Вы писали:

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


IT>>>Какой приоритет у рабочих потоков?

Tbr>>Приоритет не выставлял, потому, как итак все работает. Правда эффективность 230-270% на 4-ядернике по сравнению с однопоточным.

IT>Я бы посмотрел какой у этих потоков приоритет. Если такой же как у основного, то тогда тормоза вполне объяснимы.


Да теперь все работает идеально. Отказавшись от пула потоков в пользу обычных потоков, где это возможно, поднял КПД до 320% на 4-ядернике. А вот эффективность каждого потока по 80% можно объяснить тем, что прога 6 миллионов раз в секунду лазит в массив на 60 миллионов элементов, тут уже ничего не спасет, его же не скопируешь в каждый поток.

PS что интересно, 64-битная версия работает в 178% скорости от 32-битной, потому, как много операций над 64-битными векторами.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.