Разделить операции между несколькими потоками в С#

Вопрос:

Я пишу тестовое приложение, которое имеет число потоков и количество операций для выполнения в качестве входных параметров. Каждый тест создается как отдельный класс, который имеет метод Execute (int numberOfRepeats). numberOfRepeats – фактически количество повторений в каждом потоке.

Я создаю тесты следующим образом:

Например, у меня есть 32 потока и 50 длительных эталонных операций. Таким образом, каждый поток должен выполнить операцию 50/32 = 1 (фактически на самом деле 1,56), что даст общее число 32 операций для всех потоков.

Я использую простую конструкцию “new Thread()” для многопоточности и AutoResetEvent с конструкцией WaitHandle.WaitAll для синхронизации выполнения и измерения общего времени.

Я попробовал Parallel.For с ParallelOptions.MaxDegreeOfParallelism как число потоков, но на самом деле он не запускает тесты со всеми потоками. С числом операций 100k из threadpool с использованием ParallelOptions.MaxDegreeOfParallelism = 128 использовалось только 20 потоков.

И теперь вопрос. Как я могу разделить операции между потоками для выполнения точного числа операций в описанной ситуации?

Благодарю!

Ответ №1

Параллельный планировщик не использует так, что многие потоки, потому что он достаточно умный, чтобы знать, когда это делает, ухудшит производительность.

Из MSDN:

Пул потоков.NET динамически адаптируется к изменяющимся рабочим нагрузкам, позволяя с течением времени изменять число рабочих потоков для параллельных задач. Во время работы система наблюдает, увеличивает ли количество потоков улучшение или ухудшает общую пропускную способность и соответственно корректирует количество рабочих потоков.

Если вы используете столько потоков для выполнения теста, вам следует пересмотреть свою реализацию. Вы снижаете свою общую производительность, так как потоки будут сражаться с каждым из циклов, и это последнее, что вы хотите, когда пытаетесь выполнять работу с учетом времени, например, бенчмаркинг.

Ответ №2

Я нашел простой способ разделить любое количество операций между потоками. Этот метод возвращает массив из int, где каждый элемент означает количество операций для потока с индексом i.

    private static int[] splitTasksForThreads(int numberOfThreads, int numberOfTasks)
{
var tasksRepeatArray = new int[numberOfThreads];
var taskPerThread = numberOfTasks / numberOfThreads;
var diff = numberOfTasks - (numberOfThreads * taskPerThread);

if (diff == 0)
{
for (int i = 0; i < numberOfThreads; i++)
tasksRepeatArray[i] = taskPerThread;
}
else if (numberOfThreads > numberOfTasks)
{
for (int i = 0; i < numberOfTasks; i++)
{
tasksRepeatArray[i]++;
}
}
else
{
for (int i = 0; i < tasksRepeatArray.Length; i++)
tasksRepeatArray[i] = taskPerThread;
for (int i = 0; i < diff; i++)
tasksRepeatArray[i]++;
}

return tasksRepeatArray;
}

Оцените статью
TechArks.Ru
Добавить комментарий