Могу ли я использовать все 4 ядра процессора Raspberry Pi?


11

Мне было интересно, есть ли простой способ «включить» все 100% ЦП, чтобы я мог быстрее запускать процессы (например, вычисления на python).

1) возможно ли это?

2) Есть ли простой способ вернуться к нормальной жизни?

3) Есть ли способ использовать меньше процессора при желании?

Я думаю о взаимодействии командной строки, как:

pi@raspberry:~ $ sudo turnOnFourCores python run.py


1
Короткий ответ: нет
Стив Робиллард

16
Длинный ответ: «Если бы это было так просто, это было бы по умолчанию»
Shadow

18
Оба ваших комментария вводят в заблуждение и могут означать, что Pi имеет 4 ядра, но использует только 1. Лучше ответить, что все четыре ядра уже включены , но Python (и любая другая программа, в этом отношении) будет использовать только больше чем 1 ядро, если они не многопоточные. Из-за глобальной блокировки интерпретатора Python все еще может эффективно зависнуть, используя одно ядро, даже с многопоточностью, но это немного выходит за рамки этого вопроса.
Sohcahtoa82

13
Чтобы уточнить, я думаю, что у ОП есть неправильное понимание того, как работают многоядерные процессоры, а ваши ответы только усиливают их недопонимание.
Sohcahtoa82

6
Самый простой способ ускорить выполнение программы на Python - это переписать на скомпилированном языке (или, по крайней мере, заставить критически важные задачи использовать модуль ac).
Milliways

Ответы:


21

По умолчанию любой компьютер будет пытаться использовать все свои ядра, когда это возможно. Тем не менее, он может достичь этого только тогда, когда приложение является многопоточным. Если это не так (т.е. скрипт Python, который не использует threadingмодуль), то он может использовать максимум одно ядро. Это соответствует 25% ЦП на четырехъядерном процессоре. Если вы хотите изменить свой сценарий для использования нескольких ядер, вы можете разделить вычисления на несколько частей и создать многопоточность, как показано в документации по Python .

Обновить:

Как ответил Anon , это не сработает без работы с GIL Python (Global Interpreter Lock). Это позволяет задачам работать (казалось бы) одновременно, но не позволяет коду запускаться на нескольких ядрах. Если вы используете модули, написанные на C (например, numpy), они могут позволить вам использовать несколько ядер, чтобы обойти это ограничение. Кроме того, если это не вариант, Python предлагает многопроцессорность , которая позволяет запускать любые задачи на нескольких ядрах.


Обновление, которое является правильным, объясняет, почему первая часть ответа неверна по отношению к Python. Вы можете обойти это ограничение Python, только написав модули C или некоторый скомпилированный язык, и в этот момент вы вообще больше не пишете Python. Если производительность критична, правильный выбор - перейти на скомпилированный язык. (Многопроцессорная обработка - это не то же самое с точки зрения использования ресурсов.)
Кирпич

4
@ Кирпич Просто для ясности, скомпилированный язык не является обязательным требованием для правильной многопоточности в процессе. Черт, даже GIL в Python - это деталь реализации (предоставленная для популярного CPython) - есть другие интерпретаторы Python, которые будут успешно работать в многопоточном режиме, например, Jython и IronPython.
Боб

4
Добавление к путанице, Python будет скомпилирован; в случае CPython он компилируется в байт-код CPython, который запускается в виртуальной машине CPython. Для Jython он скомпилирован в байт-код Java, который выполняется в JVM. И наконец, IronPython компилируется в CIL, который предназначен для среды выполнения .NET. Таким образом, «переход на скомпилированный язык» для производительности не имеет никакого смысла;)
marcelm

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

13

Мне было интересно, есть ли простой способ «включить» все 100% ЦП, чтобы я мог быстрее запускать процессы (например, вычисления на python).

Не в том смысле, что я думаю, что вы намекаете. Это не проблема, специфичная для pi, это логическое ограничение.

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

Рассмотрим следующее простое математическое выражение:

(4 + 2) * 17 / (3 + 6)

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

#1 a) 4 + 2 b) 6 * 17 c) 102 / 9
#2 a) 3 + 6

Поток № 2 внес свой вклад путем вычисления 3 + 6 = 9, использованного на шаге C потоком # 1, сохранив его на один шаг. Но это то, насколько параллелизм будет полезен здесь. В то время как поток № 2 мог бы вычислять 17/9, в то время как № 1 выполняет 6 * 17, делать это было бы бессмысленно, потому что теперь у вас есть два разных пути к одной и той же цели, которые невозможно объединить. То есть, # 2 может продолжать работать:

b) 17 / 9 c) 1.888 * 6

И в итоге получается тот же результат, что и в потоке № 1 (11.333), но они не помогли друг другу после шага А, поэтому выполнение двух из них для достижения этой цели - пустая трата времени.

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

Для эксплуатации нескольких процессоров необходим код, который написан для этого. Вы не можете просто взять что-нибудь и сказать: «О, используйте все 4 ядра и делайте это быстрее!». Это не то, что случилось бы. Логично, что многие (или большинство) проблем и задач включают шаги, которые не могут происходить параллельно, они должны происходить последовательно.


1. Но см. Комментарий Феликса Домбека ниже; Я не эксперт по ИИ. Также стоит отметить, что, согласно комментариям Питера Корде, современные наборы команд и процессоры могут использоваться ОС для параллельной оптимизации очень мелкозернистых вещей, а аппаратные конвейеры также делают это, хотя и не по ядрам (один Ядро имеет более чем одну вещь, работая над потоком инструкций в различных точках перед их окончательным выполнением). Я пытался придерживаться темы пользовательских тем здесь, поскольку я думаю, что это более или менее то, что вы получаете.


4
Я написал много параллельного числового кода, и это немного вводит в заблуждение относительно деталей. Вы не распараллеливаете на уровне отдельных арифметических операций, подобных этой. (Если мы расширимся за пределы Raspberry Pi, некоторые компиляторы и процессоры все равно будут распараллеливать некоторые из них даже вне потоковых структур.) Вы распараллеливаете целые задачи большими кусками.
Кирпич

4
@Brick «Вы не распараллеливаете на уровне отдельных арифметических операций, подобных этой». -> Конечно, нет, но я поясню, что это аналогия, а не урок многопоточного программирования.
Златовласка

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

2
В RPi3 используется суперскалярный по порядку шириной 2 en.wikipedia.org/wiki/ARM_Cortex-A53 , поэтому при тщательном планировании инструкций компилятор может по-прежнему использовать ILP, помещая две addинструкции рядом друг с другом, чтобы они могли работать в одном и том же тактовый цикл. Следующее умножение и деление остатка будет сериализовано зависимостями данных, как вы указали.
Питер Кордес

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

7

Нет для питона.

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

Python GIL не позволяет эффективно использовать несколько ядер.


4
GIL немного усложняет использование всех 4 ядер. Это никоим образом не делает это невозможным или даже действительно сложным.
Фальшивое имя

5

Использование нескольких ядер требует явного раскрытия параллелизма на уровне потоков для ОС, что обычно требует от программиста написания многопоточной программы. (Или запускать однопотоковую программу несколько раз на разных входах, например, при компиляции make -j4)

Однако компиляторы для некоторых языков поддерживают автоматическое распараллеливание. Например, C или C ++ с OpenMP могут скомпилировать обычный for()цикл в программу, которая запускает несколько потоков.

#pragma omp parallel for
for(int i = 0; i < 1000000; ++i)
{
   A[i] = B[i] * constant + C[i];
}

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


Связанный: Как один поток работает на нескольких ядрах? : answer: они этого не делают. Но есть и другие виды параллелизма, такие как параллелизм на уровне инструкций, который одно ядро ​​ЦПУ находит и использует для запуска одного потока быстрее, чем одна инструкция за раз.

Мой ответ на этот вопрос касается некоторых деталей того, как современные процессоры находят и используют детализированный параллелизм на уровне команд. (В основном с упором на x86). Это лишь часть того, как работают нормальные процессоры, когда в полете одновременно выполняется несколько инструкций, и это не то, что вам нужно специально включать. (Существуют счетчики производительности, которые позволяют увидеть, сколько инструкций за такт удалось выполнить вашему ЦП во время выполнения программы или других мер.)

Обратите внимание, что RPi3 использует процессорные ядра ARM Cortex-A53 . Каждое ядро ​​имеет суперскалярную ширину 2 (2 инструкции за такт, как позволяет ILP), но не может переупорядочивать команды, чтобы найти больше параллелизма на уровне команд и скрыть задержку.

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

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

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


Все это не очень удобно, когда ваш код работает медленнее, чем вам хотелось бы. Конечно, в Cortex-A53 под капотом много классных вещей, но в Cortex-A57 под капотом есть больше классных вещей (например, выполнение не по порядку до 3 инструкций за такт), и даже больше в большой процессор x86, такой как Skylake (не говоря уже о разнице в тактовой частоте).

Cortex-A53 довольно фантастичен по сравнению с https://en.wikipedia.org/wiki/Classic_RISC_pipeline, как оригинальные MIPS, о которых вы узнаете в классе компьютерной архитектуры, но по современным стандартам это довольно низкоуровневая версия.


1
«Современное оборудование и операционные системы не могут использовать несколько ядер для ускорения однопоточной программы». это не СТРОГО верно. Например, в однопоточной Java-программе Java может выполнять все свои сборочные операции и анализ / компиляцию во время выполнения на дополнительных ядрах ЦП. Анализ во время выполнения является большой проблемой, потому что он может решить провести некоторые оптимизации, основанные на путях выполнения кода, не тратя ничего на «один поток», и может значительно ускорить его с учетом того, что он узнал из анализа. В целом, хотя ваша точка зрения хорошая.
Билл К

@BillK Честно говоря, «программа» в этом контексте - javaнет myapp.jar, и, конечно, она не однопоточная.
Златовласка

1
Правда, я просто указывал, что в зависимости от того, как была разработана среда выполнения, «код, который вы пишете», даже если он однопоточный, может использовать дополнительные ядра без явного кодирования его как многопоточного приложения. Python также может предоставить более мощную среду выполнения, но это будет бессмысленно. В любом случае, это не большой скачок - я думаю, что даже Java использует только дополнительные 1/2 ядра, чтобы помочь с однопоточным приложением.
Билл К

« У современного оборудования и операционных систем нет возможности использовать несколько ядер для ускорения однопоточной программы », и сразу после этого вы объясняете, как оборудование выполняет инструкции параллельно.
Томас Веллер

3
@ThomasWeller Да, но чтобы быть разборчивым, конвейерная обработка процессора не использует несколько ядер; он содержится в одном ядре, но позволяет работать с несколькими потоками команд. То есть это форма параллелизма, но это не форма многоядерности.
Златовласка

4

Это не так, как работают процессоры ... вообще.

В настоящее время ваш процессор прекрасно способен работать на 100% при условии, что он не регулируется из-за проблем, связанных с температурой 80 градусов Цельсия или более. При этом, вы (как правило) не хотите видеть привязку вашего процессора к 100%. Если вы обычно используете процессор на 100%, вы, вероятно, слишком много для вашего процессора. Это приведет к заиканию и, как правило, к недовольству пользователей.

Если сравнивать с чем-то более физическим, то загрузка вашего процессора во многом напоминает автомобиль. Автомобиль, вероятно, способен развивать скорость 100 миль в час, но есть большая вероятность, что ваш спидометр что-то значительно из-за этого прочитает. Находясь в городе, вы никогда не сможете разогнаться до 25 миль в час. Это, однако, не меняет того, что машина может разгоняться до 100 миль в час. Вы просто не нажали на акселератор достаточно сильно.

Если вы просто заставите RPi делать больше вещей (больше нажимать на ускоритель), вы увидите, что показатель использования ЦП будет расти. Например, следите за загрузкой процессора, когда вы запускаете команду yesв окне терминала (помните, что ctrl+cкоманды терминала заканчиваются). Это увеличит ваш ЦП на 25%, так как оно увеличит одно из четырех ваших ядер ЦП.


5
Я думаю, что этот ответ вводит в заблуждение, когда говорят, что вы обычно не хотите, чтобы ваш процессор работал с 100% загрузкой. Существует множество приложений, интенсивно работающих с цифровыми данными, в которых вам абсолютно необходимо 100% -ное использование, потому что вы посвятили машину (или машины) для расчетов. Чтобы получить настоящее время работы суперкомпьютера, вам часто приходится доказывать, что ваш код оптимизирован достаточно хорошо, чтобы сделать это, иначе они откажутся от вас как трата ресурсов. Если у вас есть кластер Pi, вы, очевидно, не получаете суперкомпьютерную производительность, но это может сделать более важным максимальное использование, а не меньшее!
Кирпич

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

100% загрузка ЦП, как правило, не вызывает плохой UX. Даже 1000% могут быть достаточно хорошими, так как большинство программ не ограничены процессором, а другими факторами. Единственными программами, которые становятся медленными из-за чрезмерной загрузки ЦП, являются программы, которые фактически используют ЦП все время.
Оскар Ског

4

Другие ответы дают хорошие детали, но, кажется, не обращаются конкретно к вашему вопросу (ам).

  1. Да, если программа (и операционная система) запрограммированы на учет нескольких ядер. («Threading» - это термин в программировании здесь)
  2. Машина использует столько или меньше каждого ядра, сколько нужно для выполнения задачи. поэтому нет необходимости что-либо менять.
  3. Вы можете установить ограничения на максимальное использование, но в нормальном использовании нет необходимости. посмотрите ответы здесь: - /unix/151883/limiting-processes-to-not-exceed-more-than-10-of-cpu-usage

NB:

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


2

Если возможно, я бы параметризировал скрипт и выполнял их в отдельных процессах Python. Например:

cat parameters.txt | xargs -n1 -P4 python run.py

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


Первая часть: Да, предполагая, что проблема под рукой, смущающе параллельна .
Питер Мортенсен

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

1

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

Для получения дополнительной информации, вы можете прочитать больше о хорошо известном заголовке статьи "Бесплатный обед окончен" http://www.gotw.ca/publications/concurrency-ddj.htm


0

Если вы хотите проверить свой RPI. Вы можете запустить stressкак здесь , тогда вы можете увидеть, как ваши процессоры используются с htop. Это полезно, потому что вы можете увидеть, достаточно ли вашего источника питания, если этого недостаточно, ваш RPI попытается использовать слишком большой ток (сила тока), и он отключится.

С другой стороны, если вы хотите использовать сценарии Python, вы должны увидеть, joblibкакой из них отлично работает, когда вы хотите распараллелить процессы, и, таким образом, вы будете использовать желаемое количество процессоров.


0

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

while True:
  x = 1.0

откройте терминал с вашего рабочего стола RPi и введите, $ topкоторый покажет работу процессора. Затем откройте другой терминал, и python3 temp.pyвы увидите, что работа Python3 возрастает до 100% процессорного времени. Затем откройте другой терминал и повторите процесс и посмотрите, как вы двигаетесь до 400%. Так что на одном уровне, как прокомментировал @Shadow, все так просто, и это значение по умолчанию. Однако проектирование программ, которые могут использовать параллельную обработку, нетривиально, как объяснили другие.


0

Ответ звучит ДА! Вы просто должны написать свою программу, чтобы распознать их и использовать их. Программы, которые делают это, могут использовать ядра. Я пишу свой, чтобы сделать это на Java, и, таким образом, я могу.

Приведенные выше ответы от разработчиков Python имеют очень ограниченную концепцию этого ответа и поэтому могут быть очень запутанными, но ответ ДА ​​и только ДА!


Можете ли вы уточнить?
SDsolar

0

Поскольку OP не указал python в своем вопросе, я хотел бы предложить еще два современных языка, которые прекрасно работают на Raspberry Pi и имеют очень простые способы использования параллелизма.

Мой текущий фаворит - язык Rust. Я написал и скомпилировал программы на Пи. Rust хорош тем, что он предотвращает многие типы ошибок указателя и состояния гонки, что делает написание параллельного кода более простым и безопасным. Rust предназначен для языка системного программирования, но он может делать практически все, что может делать C.

Другой такой язык - Go (также называется Golang, чтобы облегчить поиск). Go был создан командой Google и является достаточно зрелым языком. Легко сделать сопрограммы в Go, которые они называют «подпрограммами Go».

Оба эти языка могут компилировать код на Raspberry Pi, даже на Pi Zero. Тем не менее, они оба могут быть кросс-компилированы с более быстрого компьютера, что хорошо для больших программ.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.