У меня есть метод на C #, который я хочу запускать из нескольких потоков, скажем, 20 раз в консольном приложении на 4-х ядерная машина. Проблема, с которой я столкнулся, заключается в том, что результаты не такие, как я ожидал. Когда я запускаю метод 25 раз подряд, затраченное время равно X, и я вижу в perfmon, что максимальный процессор составляет 100% (он сообщает мне, что он использует 1 ядро). Запуская тот же метод с использованием нескольких потоков, я ожидаю, что время выполнения будет X / 4, а также я ожидаю, что максимальное использование ЦП в perfmon составит 400% (поскольку это 4-ядерная машина). Однако я могу видеть только то, что время выполнения - X / 2, а максимальная загрузка ЦП никогда не превышала 275%. Я пробовал разные вещи, такие как создание моих собственных потоков, использование потокового пула и т. Д., И ничего не работает. Может кто-нибудь объяснить / помочь мне лучше понять это?
Другой интересный момент заключается в том, что если я заменю свой метод фиктивной задачей, используя Thread.SpinWait (x)
, время выполнения будет X / 4, и я можно увидеть, что максимальный процессор достигает 400%. Это говорит мне, что в моем методе что-то не так, и я не понимаю, что это такое. У меня в методе нигде нет блокировок / сна. Ниже приведен код, который я использую для выполнения:
public static void DoWorkParallel()
{
var s = new List<string> { "a", "b", "c", "d", "e", etc. };
s.ParallelForEach2(x =>
{
MyTask(x);
});
}
public static void DoWorkSequential()
{
var s = new List<string> { "a", "b", "c", "d", "e", etc. };
foreach (var ss in s)
{
MyTask(x);
}
}
public static void ParallelForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
var results = collection.Skip(1).Select(item => new
{
action,
res = action.BeginInvoke(item, null, null)
}).ToArray();
action(collection.First()); /* let the mainthread do a job too*/
foreach (var r in results)
{
r.action.EndInvoke(r.res); /*then wait the rest of time */
}
}