Увидел хабратопик «Программирование параллельных процессов — это слишком сложно?», и понял, что здесь есть хабралюди, которым это интересно. Не удержался выразить своё мнение по этому поводу.
Кратко, суть в том, что производители процессоров (в часности Intel) перестали повышать тактовую частоту, а вместо этого идут по пути увеличения количества ядер в одном процессоре. Более того, сейчас многоядерные процессоры массово применяются для производства не только серверов, но и десктопов. При этом подавляющее большинство программ для десктопов сейчас однопоточны и на многоядерных процессорах быстрее они работать не будут. Если запустить таких программ несколько, и программы одновременно захотят использовать процессорное время, то вместе они будут работать быстрее. Но, на мой взгляд, это не то, чего ожидает пользователь десктопа от новых процессоров. И поэтому есть опасения, что пользователи могут не захотеть проапгрейдить свой двухядерный десктоп до, например восьмиядерного.
Поэтому Intel и заинтересована в том, что бы производители программных продуктов писали многопоточные программы для десктопов.
Однако не всё так просто. Особенно для производителей программных продуктов.
Проблем две. Во-первых, при современном уровне развития языков программирования, создавать многопоточные программы во много раз дороже (дороже потому что во много раз сложнее), чем однопоточные. Во-вторых, эти программы получаются намного худшего качества из-за сложности связанной с недетерминизмом, который присущ многопоточности.
Эдвард А. Ли в статье «Проблемы с потоками» пишет: «Я утверждаю, что в большинстве случаев надежность и предсказуемость работы систем не может быть достигнута при использовании потоков».
Думаю, что, призывая программистов повышать свою квалификацию (тем самым повышая свою стоимость для найма, и тем самым ухудшая будущее качество программ для десктопов) Intel не добьётся значительных результатов.
Однако не трудно проследить причину, по которой возникли обе эти проблемы. Все высокоуровневые языки, о которых я что-либо знаю, включая такие как Java, C# и C++ заставляют высокоуровневого программиста, который хочет писать многопоточные программы, явным образом манипулировать такими низкоуровневыми понятиями как поток, мутекс, монитор и обмен сообщениями.
На мой взгляд, это и есть причина всех сегодняшних бед с многопоточным программированием – высокоуровневых программистов вынуждают манипулировать низкоуровневыми понятиями, которые в большей степени относятся к операционной системе, а не к программе для конечного пользователя. И пока эта проблема не будет устранена, многопоточность никогда не станет массовой практикой (mainstream-ом) для десктопов. Как бы Intel этого не хотел.
Эта причина схожа с той, которая вызывала проблемы с памятью и была устранена сборщиком мусора. А именно – высокоуровневых программистов С++ заставляли массово и постоянно управлять памятью явно манипулируя такими низкоуровневыми понятиями как выделение и освобождение памяти. После того, как эту работу на себя взяла виртуальная машина, предоставив программисту сборщик мусора, проблема работы с памятью исчезла.
Поэтому новая технология для многопоточности должна делать для управления потоками то же самое, что сейчас сборщик мусора делает для управления памятью, а именно брать на себя всю работу по манипулированию потоками, предоставляя высокоуровневым программистам возможность писать многопоточные программы исключительно в терминах классов, объектов и зависимостей между этими классами и объектами. Т.е. новая технология должна автоматически распараллеливать определённым образом написанные высокоуровневые программы. Кстати, я считаю, что информации о зависимостях между объектами достаточно не только для сборки мусора, но и для такого автоматического распараллеливания.
Ещё я думаю, что мою идею будет относительно легко доказать, написав фреймворк в виде библиотеки для уже существующего языка. Естественно, что такая библиотека не сможет гарантировать потокобезопасность (thread safety) всей системы. Точно также как сборщик мусора, написанный в виде библиотеки (в отличие от встроенного в виртуальную машину), не может гарантировать типобезопасность (type safety) всей системы. Но, во-первых, для доказательства жизнеспособности концепции этого будет достаточно, а во-вторых, новый программный код можно будет использовать вместе со старым, написанным ранее.
Есть много путей реализовать на практике такой framework. Один из тех, которые я вижу — основать его на принципе «впрыскивания зависимостей» (dependency injection) в виде Inversion of Control контейнера. Т.е. обязывая программиста определённым образом декларировать зависимости между объектами или классами. В будущем, виртуальная машина или компилятор смогут пресекать обращения одного объекта к другому, если не была задекларирована зависимость между ними, либо автоматически выставлять тип зависимости между ними по умолчанию.
В будущем думаю, придётся также отказаться (по крайней мере, частично) и от использования стека для обеспечения потока управления (control flow), заменив стек, например графом. Стек хорошо подходит для выполнения программы в одном потоке, но является атавизмом, который препятствует появлению в многопоточных программах высокого уровня параллелизма (massive parallelism).
Кратко, суть в том, что производители процессоров (в часности Intel) перестали повышать тактовую частоту, а вместо этого идут по пути увеличения количества ядер в одном процессоре. Более того, сейчас многоядерные процессоры массово применяются для производства не только серверов, но и десктопов. При этом подавляющее большинство программ для десктопов сейчас однопоточны и на многоядерных процессорах быстрее они работать не будут. Если запустить таких программ несколько, и программы одновременно захотят использовать процессорное время, то вместе они будут работать быстрее. Но, на мой взгляд, это не то, чего ожидает пользователь десктопа от новых процессоров. И поэтому есть опасения, что пользователи могут не захотеть проапгрейдить свой двухядерный десктоп до, например восьмиядерного.
Поэтому Intel и заинтересована в том, что бы производители программных продуктов писали многопоточные программы для десктопов.
Однако не всё так просто. Особенно для производителей программных продуктов.
Проблем две. Во-первых, при современном уровне развития языков программирования, создавать многопоточные программы во много раз дороже (дороже потому что во много раз сложнее), чем однопоточные. Во-вторых, эти программы получаются намного худшего качества из-за сложности связанной с недетерминизмом, который присущ многопоточности.
Эдвард А. Ли в статье «Проблемы с потоками» пишет: «Я утверждаю, что в большинстве случаев надежность и предсказуемость работы систем не может быть достигнута при использовании потоков».
Думаю, что, призывая программистов повышать свою квалификацию (тем самым повышая свою стоимость для найма, и тем самым ухудшая будущее качество программ для десктопов) Intel не добьётся значительных результатов.
Однако не трудно проследить причину, по которой возникли обе эти проблемы. Все высокоуровневые языки, о которых я что-либо знаю, включая такие как Java, C# и C++ заставляют высокоуровневого программиста, который хочет писать многопоточные программы, явным образом манипулировать такими низкоуровневыми понятиями как поток, мутекс, монитор и обмен сообщениями.
На мой взгляд, это и есть причина всех сегодняшних бед с многопоточным программированием – высокоуровневых программистов вынуждают манипулировать низкоуровневыми понятиями, которые в большей степени относятся к операционной системе, а не к программе для конечного пользователя. И пока эта проблема не будет устранена, многопоточность никогда не станет массовой практикой (mainstream-ом) для десктопов. Как бы Intel этого не хотел.
Эта причина схожа с той, которая вызывала проблемы с памятью и была устранена сборщиком мусора. А именно – высокоуровневых программистов С++ заставляли массово и постоянно управлять памятью явно манипулируя такими низкоуровневыми понятиями как выделение и освобождение памяти. После того, как эту работу на себя взяла виртуальная машина, предоставив программисту сборщик мусора, проблема работы с памятью исчезла.
Поэтому новая технология для многопоточности должна делать для управления потоками то же самое, что сейчас сборщик мусора делает для управления памятью, а именно брать на себя всю работу по манипулированию потоками, предоставляя высокоуровневым программистам возможность писать многопоточные программы исключительно в терминах классов, объектов и зависимостей между этими классами и объектами. Т.е. новая технология должна автоматически распараллеливать определённым образом написанные высокоуровневые программы. Кстати, я считаю, что информации о зависимостях между объектами достаточно не только для сборки мусора, но и для такого автоматического распараллеливания.
Ещё я думаю, что мою идею будет относительно легко доказать, написав фреймворк в виде библиотеки для уже существующего языка. Естественно, что такая библиотека не сможет гарантировать потокобезопасность (thread safety) всей системы. Точно также как сборщик мусора, написанный в виде библиотеки (в отличие от встроенного в виртуальную машину), не может гарантировать типобезопасность (type safety) всей системы. Но, во-первых, для доказательства жизнеспособности концепции этого будет достаточно, а во-вторых, новый программный код можно будет использовать вместе со старым, написанным ранее.
Есть много путей реализовать на практике такой framework. Один из тех, которые я вижу — основать его на принципе «впрыскивания зависимостей» (dependency injection) в виде Inversion of Control контейнера. Т.е. обязывая программиста определённым образом декларировать зависимости между объектами или классами. В будущем, виртуальная машина или компилятор смогут пресекать обращения одного объекта к другому, если не была задекларирована зависимость между ними, либо автоматически выставлять тип зависимости между ними по умолчанию.
В будущем думаю, придётся также отказаться (по крайней мере, частично) и от использования стека для обеспечения потока управления (control flow), заменив стек, например графом. Стек хорошо подходит для выполнения программы в одном потоке, но является атавизмом, который препятствует появлению в многопоточных программах высокого уровня параллелизма (massive parallelism).