У меня 50 агентов машинного обучения.Каждый кадр, они получают некоторые входы и вычисляют нейронную сеть.Поскольку каждый агент независим, я бы хотел, чтобы каждый агент вычислял сеть как отдельную задачу.
Если бы мне нужно было создать задачу для каждого агента, каждого кадра, это замедлило бы мою программу.Я пытался сгруппировать своих агентов в 2 задачи (25 и 25), но это все еще было непроизводительным расходом.
На мой взгляд, это создать n потоков для n групп агентов в начале и запросить их.каждый кадр как-нитьПоток вычислит сеть для группы агентов, а затем дождется следующего запроса.
Я прочитал несколько статей на эту тему и обнаружил, что не могу повторно использовать задачу.Итак, какой обходной путь может сработать?
По сути, я повторяю действие на 50 агентах, то есть запускаю каждый кадр примерно минуту, и не стоит тратить время на их параллелизацию.
Я все еще плохо знаком с многопоточностью и задачами, поэтому полагаюсь на вашу помощь.Примечания: я использую генетические алгоритмы в Unity.Вот код, в котором я попытался разделить агентов на n групп и вычислить их сети по n задачам.
public async Task EvaluateAsync(int groupSize = 10)
{
var groups = genomes.Select((g, i) => new { Value = g, Index = i })
.GroupBy(x => x.Index / groupSize)
.Select(x => x.Select(v => v.Value));
var tasks = groups.Select(g =>
{
return Task.Run(() =>
{
foreach (var element in g)
element.Fitness += ComputeFitness(element as NeuralGenome);
});
}).ToArray();
for (var i = 0; i < tasks.Length; i++)
await tasks[i];
}
И в функции Update()
, которую я вызываю:
EvaluateAsync(25).Wait();
Это немного быстрее, когда сеть очень большая, но гораздо медленнее, когда имеется всего 10 нейронов.
Уменьшение групп приведет к повышению производительности, только если сети оченьогромный.
Здесь я создаю задание для каждого агента:
public async Task EvaluateAsyncEach()
{
var tasks = genomes.Select(x => Task.Run(() => x.Fitness += ComputeFitness(x as NeuralGenome)))
.ToArray();
foreach (var task in tasks)
await task;
}
Следующие измерения сделаны для 10 кадров.Значение t / 10 будет временем выполнения одной задачи.
Время нормальной работы:
00:00:00.3791190
00:00:00.3758430
00:00:00.3697020
00:00:00.3743900
00:00:00.3764850
Одна задача для каждого агента в каждом кадре:
00:00:01.1288240
00:00:01.0761770
00:00:00.9311210
00:00:01.0122570
00:00:00.8938200
В группах по 25:
00:00:00.5401100
00:00:00.5629660
00:00:00.5640470
00:00:00.5932220
00:00:00.6053940
00:00:00.5828170