Сторонники FP утверждают, что параллелизм прост, потому что их парадигма избегает изменчивого состояния. Я не понимаю
Я хотел бы рассказать об этом общем вопросе как о человеке, который является функциональным неофитом, но в течение многих лет испытывал побочные эффекты, и хотел бы смягчить их по разным причинам, включая более простые (или особенно «более безопасные», меньше ошибок ") параллелизм. Когда я смотрю на своих функциональных коллег и то, что они делают, трава кажется немного зеленее и пахнет лучше, по крайней мере, в этом отношении.
Последовательные алгоритмы
Тем не менее, в вашем конкретном примере, если ваша проблема носит последовательный характер и B не может быть выполнен до тех пор, пока A не закончится, концептуально вы не сможете запустить A и B параллельно, несмотря ни на что. Вы должны найти способ разорвать зависимость порядка, как в своем ответе, на основе выполнения параллельных ходов, используя старое игровое состояние, или использовать структуру данных, которая позволяет независимо изменять ее части, чтобы устранить зависимость порядка, как предложено в других ответах. или что-то в этом роде. Но есть определенная доля концептуальных проблем дизайна, таких как эта, когда вы не можете просто так просто многопоточить все, потому что вещи неизменны. Некоторые вещи будут носить последовательный характер, пока вы не найдете какой-нибудь умный способ разорвать зависимость от порядка, если это вообще возможно.
Более простой параллелизм
Тем не менее, есть много случаев , когда мы не в состоянии распараллеливания программ , которые включают побочные эффекты в местах , которые потенциально могли бы значительно улучшить производительность просто из - за возможности того, что он может не быть потокобезопасным. Один из случаев, когда устранение изменяемого состояния (или, более конкретно, внешних побочных эффектов) очень помогает, как я вижу, состоит в том, что он превращает «может быть, а может и не быть потокобезопасным» в «определенно потокобезопасный» .
Чтобы сделать это утверждение более конкретным, рассмотрим, что я даю вам задачу реализовать функцию сортировки в C, которая принимает компаратор и использует его для сортировки массива элементов. Он должен быть довольно обобщенным, но я дам вам легкое предположение, что он будет использоваться против входных данных такого масштаба (миллионы элементов или более), что, несомненно, будет выгодно всегда использовать многопоточную реализацию. Можете ли вы многопоточность вашей функции сортировки?
Проблема в том, что вы не можете этого сделать, потому что компараторы, вызываемые вашей функцией сортировки, могутвызывать побочные эффекты, если вы не знаете, как они реализованы (или, по крайней мере, документированы) для всех возможных случаев, что невозможно без дегенерализации функции. Компаратор может сделать что-то отвратительное, например модифицировать глобальную переменную внутри неатомарным способом. 99,9999% компараторов могут этого не делать, но мы все еще не можем многопоточность этой обобщенной функции просто из-за 0,00001% случаев, которые могут вызывать побочные эффекты. В результате вам, возможно, придется предложить как однопоточную, так и многопоточную функцию сортировки и передать ответственность программистам, использующим ее, чтобы решить, какую из них использовать, основываясь на безопасности потоков. И люди могут все еще использовать однопоточную версию и упустить возможности многопоточности, потому что они также могут быть не уверены, является ли компаратор потокобезопасным,
Существует целый ряд умственных способностей, которые можно задействовать, просто рационализируя безопасность потоков, не создавая повсюду блокировок, которые могут исчезнуть, если бы у нас были твердые гарантии того, что функции не будут вызывать побочных эффектов ни сейчас, ни в будущем. И есть страх: практический страх, потому что любой, кто должен был отладить состояние гонки несколько слишком много раз, вероятно, будет колебаться из-за многопоточности всего, что не может быть на 110% уверенным в потоке и останется таковым. Даже для самого параноика (с которым я, вероятно, по крайней мере граничу), чистая функция обеспечивает то чувство облегчения и уверенности, что мы можем безопасно вызывать его параллельно.
И это один из основных случаев, когда я считаю очень полезным, если вы можете получить твердую гарантию, что такие функции являются поточно-ориентированными, что вы получаете с чисто функциональными языками. Другой заключается в том, что функциональные языки часто способствуют созданию функций, в первую очередь свободных от побочных эффектов. Например, они могут предоставить вам постоянные структуры данных, где достаточно эффективно вводить массивную структуру данных, а затем выводить совершенно новую, только небольшую часть которой изменили по сравнению с оригиналом, не касаясь оригинала. Те, кто работает без таких структур данных, могут захотеть изменить их напрямую и потерять некоторую безопасность потоков.
Побочные эффекты
Тем не менее, я не согласен с одной частью при всем уважении к моим функциональным друзьям (которые я считаю супер крутой):
[...] потому что их парадигма избегает изменчивого состояния.
Это не обязательно неизменность, которая делает параллелизм настолько практичным, насколько я понимаю. Это функции, которые не вызывают побочных эффектов. Если функция вводит массив для сортировки, копирует его, а затем изменяет копию для сортировки ее содержимого и выводит копию, она все еще так же поточно-ориентированная, как и та, которая работает с некоторым типом неизменяемого массива, даже если вы передаете тот же самый ввод массив к нему из нескольких потоков. Поэтому я думаю, что для изменяемых типов все еще есть место для создания кода, очень дружественного к параллелизму, хотя есть много дополнительных преимуществ для неизменяемых типов, включая постоянные структуры данных, которые я использую не столько для их неизменяемых свойств, сколько для избавьтесь от необходимости глубокого копирования всего, чтобы создавать функции без побочных эффектов.
И часто бывает непросто сделать функции свободными от побочных эффектов в виде перетасовки и копирования некоторых дополнительных данных, возможно, дополнительного уровня косвенности, и, возможно, некоторого GC на части постоянной структуры данных, но я смотрю на одного из моих приятелей, у которого есть 32-ядерная машина, и я думаю, что обмен, вероятно, того стоит, если мы сможем более уверенно делать больше вещей параллельно.