Я недавно спросил о функциональных программах, имеющих побочные эффекты, и изучил то, что это означает для того, чтобы сделать параллелизированные задачи тривиальными. А именно, тот "чистые" функции делают это тривиальным, поскольку у них нет побочных эффектов.
Я также недавно изучал LINQ и лямбда-выражения, поскольку я много раз натыкался на примеры здесь на StackOverflow, включающем перечисление. Это получило меня к удивлению при параллелизации перечисления, или цикл может быть "легче" в C# теперь.
Действительно ли лямбда-выражения Достаточно "чисты" для осуществления тривиальной параллелизации? Возможно, это зависит от того, что Вы делаете с выражением, но они могут быть достаточно чистыми? Что-то вроде этого было бы теоретически возможно/тривиально в C#?:
Например, скажите, что у меня был набор объектов в игровом цикле (поскольку я разрабатываю игру и думал о возможности нескольких потоков), и должен был сделать что-то с каждым из них каждый кадр, вышеупомянутое будет тривиально для осуществления? Рассмотрение IEnumerable, это кажется им только, отслеживает текущую позицию, таким образом, я не уверен, что мог использовать нормальные универсальные наборы для повреждения перечисления в "блоки".
Извините за этот вопрос. Я использовал маркеры выше вместо псевдокода, потому что я даже не знаю достаточно для записи псевдокода первое, что пришло на ум. Мое знание.NET было чисто простым бизнес-материалом, и я плохо знаком с делегатами и потоками и т.д. Я главным образом хочу знать, хорош ли вышеупомянутый подход для преследования, и если делегаты/лямбды не должны быть взволнованы по поводу когда дело доходит до их распараллеливания.
Прежде всего, обратите внимание, что для того, чтобы метод был «чистым», он не должен иметь только побочных эффектов. Он также должен всегда возвращать один и тот же результат, если заданы одни и те же аргументы. Так, например, метод "Math.Sin" чистый. Вы кормите 12, это возвращает вам грех (12), и это всегда одно и то же. Метод GetCurrentTime () не является чистым, даже если у него нет побочных эффектов; он возвращает другое значение каждый раз, когда вы вызываете его, независимо от того, какие аргументы вы передаете.
Также обратите внимание, что чистый метод действительно не должен генерировать исключение; исключения считаются наблюдаемыми побочными эффектами для наших целей.
Во-вторых, да, если вы можете рассуждать о чистоте метода, вы можете делать интересные вещи для его автоматического распараллеливания. Проблема в том, что практически нет чистых методов. Более того, предположим, что у вас есть чистый метод; поскольку чистый метод - идеальный кандидат для мемоизации, и поскольку мемоизация вызывает побочный эффект (мутирует кеш!), очень привлекательно брать то, что должно быть чистыми методами, а затем делать их нечистыми.
Что нам действительно нужно, так это какой-то способ «приручить побочные эффекты», как говорит Джо Даффи. Какой-то способ обвести метод рамкой и сказать, что «этот метод не лишен побочных эффектов, но его побочные эффекты не видны за пределами этого поля», а затем использовать этот факт для безопасного вождения. автоматическое распараллеливание.
Мне бы хотелось придумать какой-нибудь способ добавить эти концепции к таким языкам, как C #, но здесь все это чисто пустяковые проблемы открытого исследования; никаких обещаний, предполагаемых или подразумеваемых.
Лямбда должна быть чистой. Затем FrameWork предлагает автоматическое параллелизацию с простым добавлением .AsParallel
к запросу LINQ (PLINQ).
Но это не является автоматическим или гарантированным, программист несет ответственность за их чистоту.
Чистая лямбда или нет, зависит от того, что она делает. По сути, это не чисто или нечисто.
Например: следующее лямбда-выражение является нечистым, поскольку оно считывает и записывает одну переменную в теле. При параллельном запуске возникает состояние гонки.
var i = 0;
Func<bool> del = () => {
if ( i == 42 ) { return true; }
else ( i++ ) { return false; }
};
Напротив, следующий делегат является чистым и не имеет условий гонки.
Func<bool> del = () => true;
Что касается части цикла, вы также можете использовать Parallel.For
и Parallel.ForEach
в качестве примера об объектах в игре. Это также часть .net 4, но вы можете скачать ее.
О новой поддержке параллелизма в .NET 4.0 можно прочитать 13 частей здесь. Она включает обсуждение LINQ и PLINQ также в части 7. Это отличное чтение, так что ознакомьтесь с ним
.