Многоядерное программирование: твердые части

Я пишу книгу по многоядерному программированию с помощью.NET 4, и мне любопытно знать то, что части людей многоядерного программирования нашли трудными к grok или ожидают быть трудными к grok?

14
задан Jon Harrop 5 June 2010 в 10:51
поделиться

7 ответов

Поскольку вы пишете целую книгу по многоядерному программированию в .Net.

Думаю, вы также можете немного выйти за рамки многоядерных .

Например, вы можете использовать главу, посвященную параллельным вычислениям в распределенной системе в .Net. Вряд ли в .Net пока нет зрелых фреймворков. DryadLinq - самый близкий. (С другой стороны, Hadoop и его друзья на платформе Java действительно хороши.)

Вы также можете использовать главу, демонстрирующую некоторые возможности вычислений на GPU.

5
ответ дан 1 December 2019 в 09:31
поделиться

Это не столько теоретические детали, сколько детали практической реализации, которые сбивают с толку.

Что происходит с неизменяемыми структурами данных?

Все время люди пытаются обновить структуру данных из нескольких потоков, находят это слишком сложным, и кто-то кричит «используйте неизменяемые структуры данных!», И поэтому наши постоянные coder пишет следующее:

ImmutableSet set;

ThreadLoop1()
    foreach(Customer c in dataStore1)
        set = set.Add(ProcessCustomer(c));

ThreadLoop2()
    foreach(Customer c in dataStore2)
        set = set.Add(ProcessCustomer(c));

Кодер всю свою жизнь слышал, что неизменяемые структуры данных можно обновлять без блокировки, но новый код не работает по очевидным причинам.

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

Как разделить примерно равный объем работы между потоками?

Выполнить этот шаг сложно . Иногда вы разбиваете один процесс на 10 000 шагов, которые можно выполнять параллельно, но не все шаги занимают одинаковое количество времени. Если вы разделите работу на 4 потока, и первые 3 потока заканчиваются за 1 секунду, а последний поток занимает 60 секунд, ваша многопоточная программа не намного лучше, чем однопоточная версия, верно?

Так как же сделать вы разделяете проблемы с примерно равным объемом работы между всеми потоками? Здесь должно быть уместно множество хороших эвристик для решения проблем с упаковкой контейнеров.

Сколько потоков?

Если ваша задача хорошо распараллеливается, добавление большего количества потоков должно ускорить ее, верно? Ну не совсем, здесь нужно учесть множество вещей:

Даже одноядерный процессор, добавление большего количества потоков может сделать программу быстрее, потому что большее количество потоков дает ОС больше возможностей для планирования вашего потока, поэтому он получает больше времени выполнения, чем однопоточная программа. Но с законом убывающей отдачи добавление большего количества потоков увеличивает переключение контекста, поэтому в определенный момент, даже если ваша программа имеет наибольшее время выполнения, производительность все равно может быть хуже, чем однопоточная версия.

Так как же выделить столько потоков, чтобы минимизировать время выполнения?

И если есть много других приложений, раскручивающих потоки и конкурирующих за ресурсы, как вы обнаружите изменения производительности и автоматически скорректируете свою программу?

2
ответ дан 1 December 2019 в 09:31
поделиться

Какая полезная единица работы для распараллеливания и как ее найти / организовать?

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

Таким образом, одна из больших проблем - найти единицы работы, которые явно дороже, чем примитивы параллелизма. Ключевая проблема здесь в том, что никто не знает, чего стоит выполнение чего-либо, включая сами примитивы параллелизма. Было бы очень полезно провести точную калибровку этих затрат. (Кроме того, мы разработали, внедрили и ежедневно используем язык параллельного программирования, PARLANSE , целью которого было минимизировать стоимость примитивов параллелизма, позволяя компилятору генерировать и оптимизировать их, с целью делая меньшие части работы «более распараллеливаемыми»).

Можно также рассмотреть обсуждение нотации большого О и ее приложений. Мы все надеемся, что примитивы параллелизма стоят O (1). Если это так, то если вы найдете работу со стоимостью O (x)> O (1), то эта работа является хорошим кандидатом для распараллеливания.Если предложенная вами работа также соответствует O (1), то ее эффективность зависит от постоянных факторов, и мы возвращаемся к калибровке, как указано выше.

Существует проблема сбора работы в достаточно большие единицы, если ни одна из частей не является достаточно большой. Перемещение кода, замена алгоритма ... все это полезные идеи для достижения этого эффекта.

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

7
ответ дан 1 December 2019 в 09:31
поделиться

Думаю, отчасти это зависит от того, насколько базовая или продвинутая книга / аудитория. Когда вы впервые переходите от однопоточного к многопоточному программированию, вы обычно падаете с огромной скалы (и многие никогда не восстанавливаются, см., Например, все запутанные вопросы о Control.Invoke).

В любом случае, чтобы добавить некоторые мысли, которые относятся не столько к самому программированию, сколько к другим связанным задачам в процессе разработки программного обеспечения:

  • Измерение : решение, какую метрику вы стремитесь улучшить, правильное ее измерение ( так легко случайно измерить не то), используя правильные инструменты, дифференцируя сигнал по сравнению с шумом, интерпретируя результаты и понимая, почему они такие, какие они есть.

  • Тестирование : как писать тесты, которые допускают несущественный недетерминизм / чередование, но при этом фиксируют правильное поведение программы.

  • Отладка : инструменты, стратегии, когда «трудно отлаживать» подразумевает обратную связь для улучшения вашего кода / дизайна и улучшения изменяемого состояния разделов и т. Д.

  • Физическая и логическая сходство потоков : понимание потока графического интерфейса пользователя, понимание того, как, например, Процессор / агент F # MailboxProcessor / agent может инкапсулировать изменяемое состояние и работать в нескольких потоках, но всегда только с одним логическим потоком (одним счетчиком программы).

  • Шаблоны (и когда они применимы): fork-join, map-reduce, продюсер-потребитель, ...

Я ожидаю, что будет большая аудитория, например, «Помогите, у меня есть однопоточное приложение с 12% загрузкой ЦП, и я хочу выучить ровно столько, чтобы оно работало в 4 раза быстрее без особых усилий» и меньшая аудитория, например, «мое приложение масштабируется сублинейно по мере того, как мы добавляем ядра, потому что здесь, похоже, есть разногласия, есть ли лучший подход для использования?», и поэтому небольшая проблема может заключаться в обслуживании каждой из этих аудиторий.

6
ответ дан 1 December 2019 в 09:31
поделиться

Одна вещь, которая меня сбила с толку, - это то, какой подход использовать для решения конкретного типа проблемы. Есть агенты, есть задачи, асинхронные вычисления, MPI для распространения - для многих проблем вы можете использовать несколько методов, но мне трудно понять, почему я должен использовать один вместо другого.

4
ответ дан 1 December 2019 в 09:31
поделиться

Для понимания: детали памяти низкого уровня, такие как разница между семантикой приобретения и освобождения памяти.

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

Конечно, практика, особенно если что-то иногда дает сбой, очень трудна, поскольку вам нужно работать на нескольких уровнях абстракции, чтобы понять, что происходит, так что сохраняйте свою конструкцию простой и, насколько это возможно, исключите необходимость в блокировке и т.д. (например, используя неизменяемые данные и абстракции более высокого уровня).

3
ответ дан 1 December 2019 в 09:31
поделиться

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

Обычно я также нахожу отладку медвежьим трудом.

1
ответ дан 1 December 2019 в 09:31
поделиться
Другие вопросы по тегам:

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