Являются ли лямбда-выражения / делегаты в C # "чистыми" или они могут быть? - PullRequest
5 голосов
/ 18 марта 2010

I недавно спросил о функциональных программах, не имеющих побочных эффектов, и узнал, что это значит сделать параллельные задачи тривиальными. В частности, эти «чистые» функции делают это тривиальным, поскольку они не имеют побочных эффектов.

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

Являются ли лямбда-выражения "чистыми" достаточно, чтобы осуществить тривиальное распараллеливание? Может быть, это зависит от того, что вы делаете с выражением, но могут ли они быть достаточно чистыми? Будет ли что-то подобное теоретически возможным / тривиальным в C #?

  • Разбить цикл на куски
  • Запуск потока для циклического прохождения каждого куска
  • Запустите функцию, которая делает что-то со значением из текущая позиция петли каждого потока

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

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

Ответы [ 5 ]

17 голосов
/ 18 марта 2010

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

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

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

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

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

13 голосов
/ 18 марта 2010

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

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

3 голосов
/ 18 марта 2010

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

3 голосов
/ 18 марта 2010

Чиста лямбда или нет, связана с тем, что она делает. Как концепция, она не является ни чистой, ни нечистой.

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

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

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

Func<bool> del = () => true;
2 голосов
/ 18 марта 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...