Есть готовая программа на 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 ядра, то тоже все прекрасно.
Уже всё перечитал, и про пулы потоков тоже, всё испытал, до чего мозгов хватило.
Посоветуйте, как правильно реализовать.
Tbr>1. Если убрать многопоточность, то все работает шикарно на любом количестве ядер.
... Tbr>4. Если на компьютере 4 ядра, то тоже все прекрасно.
Вообще-то запускать большое количество (больше, чем ядер в системе) потоков с вычислениями смысла не имеет. Быстрее расчет не выполнится, а будут только лишние накладные расходы на переключения между потоками и т.п.
Если все-таки надо вести несколько расчетов параллельно — то стоит нарезать исх. задание на небольшие порции и последовательно их выполнять.
Здравствуйте, andrey82, Вы писали:
A>Здравствуйте, Tbr, Вы писали:
Tbr>>1. Если убрать многопоточность, то все работает шикарно на любом количестве ядер. A>... Tbr>>4. Если на компьютере 4 ядра, то тоже все прекрасно.
A>Вообще-то запускать большое количество (больше, чем ядер в системе) потоков с вычислениями смысла не имеет. Быстрее расчет не выполнится, а будут только лишние накладные расходы на переключения между потоками и т.п.
А сколько потоков запускать, чтобы работало и на планшете с Atom и на 4*OpteronX12?
A>Если все-таки надо вести несколько расчетов параллельно — то стоит нарезать исх. задание на небольшие порции и последовательно их выполнять.
Задание философское и невыполнимое, одна кнопка начинает показывать, как горит огонь, другая, как течет вода. Надо параллельно вычислять и выводить на форму и иметь возможность выбирать новое задание 5 раз в секунду.
Я через диспетчер задач задаю соответствия, разрешаю программе пользоваться только одним ядром.
А может быть она думает, что ядра 4 и потому пытается запускать 4 потока одновременно, чем и вызывает дикие тормоза, а на реальном 1-ядерном процессоре всё будет работать?
Здравствуйте, Tbr, Вы писали:
Tbr>При нажатии на кнопку, запускается соответствующий просчет и результаты каждые 1/5 сек выводятся на форму, при нажатии на другую кнопку расчет прерывается и начинают выводиться результаты другой функции. Каждая из функций использует многопоточность и всё это вместе работает шикарно...на 4-ядерном процессоре. Стоит уменьшить количество доступных ядер до 1-2, программа начинает жестко тупить.
Всё это не то, я разобрался с проблемой. Это косяк фреймворка.
Если в диспетчере задач уменьшаешь количество ядер для программы, фреймворк сильно тупит, видит, что прога загружает проц далеко не на 100% и начинает запускать еще потоки, причем если отключишь 3 ядра, то будет накидываться за раз по 3 потока, а через 10 секунд приложение превратится в 20-поточное (с отключенными то ядрами), причем все потоки будут работать одновременно. Это вызывает дикие тормоза и глюки.
Сейчас доделаю исходник, демонстрирующий это, выложу его и можно тему закрывать.
Здравствуйте, Tbr, Вы писали:
Tbr>Здравствуйте, Mystic, Вы писали:
M>>SetThreadPriority?
Tbr>Всё это не то, я разобрался с проблемой. Это косяк фреймворка. Tbr>Если в диспетчере задач уменьшаешь количество ядер для программы, фреймворк сильно тупит, видит, что прога загружает проц далеко не на 100% и начинает запускать еще потоки, причем если отключишь 3 ядра, то будет накидываться за раз по 3 потока, а через 10 секунд приложение превратится в 20-поточное (с отключенными то ядрами), причем все потоки будут работать одновременно. Это вызывает дикие тормоза и глюки.
Убери пул потоков, создавай потоки сам и никто не будет заводить новые потоки без твоего участия. Надеюсь.
Здравствуйте, Tbr, Вы писали:
Tbr>Уже всё перечитал, и про пулы потоков тоже, всё испытал, до чего мозгов хватило. Tbr>Посоветуйте, как правильно реализовать.
Какой приоритет у рабочих потоков?
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Tbr, Вы писали:
Tbr>>Уже всё перечитал, и про пулы потоков тоже, всё испытал, до чего мозгов хватило. Tbr>>Посоветуйте, как правильно реализовать.
IT>Какой приоритет у рабочих потоков?
Приоритет не выставлял, потому, как итак все работает. Правда эффективность 230-270% на 4-ядернике по сравнению с однопоточным.
Просто через пул потоков вызываю Environment.ProcessorCount штук и всё. Проц загружен на 100% и ничего не тормозит, не знаю, зачем нужен приоритет. А вот как эффективность поднять не понимаю.
Попробуйте ThreadPool.SetMaxThreads, и вообще с настройками пула поэкпериментируйте. А вообще описанное Вами похоже на баг, попробуйте отправить репорт.
Здравствуйте, Tbr, Вы писали:
IT>>Какой приоритет у рабочих потоков? Tbr>Приоритет не выставлял, потому, как итак все работает. Правда эффективность 230-270% на 4-ядернике по сравнению с однопоточным.
Я бы посмотрел какой у этих потоков приоритет. Если такой же как у основного, то тогда тормоза вполне объяснимы.
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, IT, Вы писали:
IT>Здравствуйте, Tbr, Вы писали:
IT>>>Какой приоритет у рабочих потоков? Tbr>>Приоритет не выставлял, потому, как итак все работает. Правда эффективность 230-270% на 4-ядернике по сравнению с однопоточным.
IT>Я бы посмотрел какой у этих потоков приоритет. Если такой же как у основного, то тогда тормоза вполне объяснимы.
Да теперь все работает идеально. Отказавшись от пула потоков в пользу обычных потоков, где это возможно, поднял КПД до 320% на 4-ядернике. А вот эффективность каждого потока по 80% можно объяснить тем, что прога 6 миллионов раз в секунду лазит в массив на 60 миллионов элементов, тут уже ничего не спасет, его же не скопируешь в каждый поток.
PS что интересно, 64-битная версия работает в 178% скорости от 32-битной, потому, как много операций над 64-битными векторами.