Многопоточная задача, не использующая ЦП?

У меня есть метод на 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 */
    }
}
6
задан abatishchev 4 July 2011 в 11:48
поделиться