Находятся выражения/делегаты лямбды в “чистом” C#, или они могут быть?

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

Я также недавно изучал LINQ и лямбда-выражения, поскольку я много раз натыкался на примеры здесь на StackOverflow, включающем перечисление. Это получило меня к удивлению при параллелизации перечисления, или цикл может быть "легче" в C# теперь.

Действительно ли лямбда-выражения Достаточно "чисты" для осуществления тривиальной параллелизации? Возможно, это зависит от того, что Вы делаете с выражением, но они могут быть достаточно чистыми? Что-то вроде этого было бы теоретически возможно/тривиально в C#?:

  • Повредите цикл в блоки
  • Выполните поток для цикличного выполнения через каждый блок
  • Выполните функцию, которая делает что-то со значением от положения токовой петли каждого потока

Например, скажите, что у меня был набор объектов в игровом цикле (поскольку я разрабатываю игру и думал о возможности нескольких потоков), и должен был сделать что-то с каждым из них каждый кадр, вышеупомянутое будет тривиально для осуществления? Рассмотрение IEnumerable, это кажется им только, отслеживает текущую позицию, таким образом, я не уверен, что мог использовать нормальные универсальные наборы для повреждения перечисления в "блоки".

Извините за этот вопрос. Я использовал маркеры выше вместо псевдокода, потому что я даже не знаю достаточно для записи псевдокода первое, что пришло на ум. Мое знание.NET было чисто простым бизнес-материалом, и я плохо знаком с делегатами и потоками и т.д. Я главным образом хочу знать, хорош ли вышеупомянутый подход для преследования, и если делегаты/лямбды не должны быть взволнованы по поводу когда дело доходит до их распараллеливания.

5
задан Community 23 May 2017 в 12:31
поделиться

5 ответов

Прежде всего, обратите внимание, что для того, чтобы метод был «чистым», он не должен иметь только побочных эффектов. Он также должен всегда возвращать один и тот же результат, если заданы одни и те же аргументы. Так, например, метод "Math.Sin" чистый. Вы кормите 12, это возвращает вам грех (12), и это всегда одно и то же. Метод GetCurrentTime () не является чистым, даже если у него нет побочных эффектов; он возвращает другое значение каждый раз, когда вы вызываете его, независимо от того, какие аргументы вы передаете.

Также обратите внимание, что чистый метод действительно не должен генерировать исключение; исключения считаются наблюдаемыми побочными эффектами для наших целей.

Во-вторых, да, если вы можете рассуждать о чистоте метода, вы можете делать интересные вещи для его автоматического распараллеливания. Проблема в том, что практически нет чистых методов. Более того, предположим, что у вас есть чистый метод; поскольку чистый метод - идеальный кандидат для мемоизации, и поскольку мемоизация вызывает побочный эффект (мутирует кеш!), очень привлекательно брать то, что должно быть чистыми методами, а затем делать их нечистыми.

Что нам действительно нужно, так это какой-то способ «приручить побочные эффекты», как говорит Джо Даффи. Какой-то способ обвести метод рамкой и сказать, что «этот метод не лишен побочных эффектов, но его побочные эффекты не видны за пределами этого поля», а затем использовать этот факт для безопасного вождения. автоматическое распараллеливание.

Мне бы хотелось придумать какой-нибудь способ добавить эти концепции к таким языкам, как C #, но здесь все это чисто пустяковые проблемы открытого исследования; никаких обещаний, предполагаемых или подразумеваемых.

17
ответ дан 18 December 2019 в 05:23
поделиться

Лямбда должна быть чистой. Затем FrameWork предлагает автоматическое параллелизацию с простым добавлением .AsParallel к запросу LINQ (PLINQ).

Но это не является автоматическим или гарантированным, программист несет ответственность за их чистоту.

13
ответ дан 18 December 2019 в 05:23
поделиться

Чистая лямбда или нет, зависит от того, что она делает. По сути, это не чисто или нечисто.

Например: следующее лямбда-выражение является нечистым, поскольку оно считывает и записывает одну переменную в теле. При параллельном запуске возникает состояние гонки.

var i = 0;
Func<bool> del = () => {
  if ( i == 42 ) { return true; }
  else ( i++ ) { return false; }
};

Напротив, следующий делегат является чистым и не имеет условий гонки.

Func<bool> del = () => true;
3
ответ дан 18 December 2019 в 05:23
поделиться

Что касается части цикла, вы также можете использовать Parallel.For и Parallel.ForEach в качестве примера об объектах в игре. Это также часть .net 4, но вы можете скачать ее.

3
ответ дан 18 December 2019 в 05:23
поделиться

О новой поддержке параллелизма в .NET 4.0 можно прочитать 13 частей здесь. Она включает обсуждение LINQ и PLINQ также в части 7. Это отличное чтение, так что ознакомьтесь с ним

.
2
ответ дан 18 December 2019 в 05:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: