Есть ли процессор, который может менять переменные одновременно? - PullRequest
1 голос
/ 24 октября 2009

если я напишу:

a = 0;
b = 0;
c = 0;
d = 0;
e = 0;
f = 0;

Я думаю (возможно, ошибаюсь), что процессор будет идти строка за строкой, например:

CPU says:
let me assign a to 0
then let me assign b to 0
then let me assign c to 0
then let me assign d to 0
etc...

Мне просто интересно, есть ли процессор, который может изменять переменные одновременно ...?

Спасибо ... Y_Y

Ответы [ 7 ]

5 голосов
/ 24 октября 2009

У вас есть строка кода, а не вызов метода.

РЕДАКТИРОВАТЬ : В ответ на ваш отредактированный вопрос ... для этого вам понадобится векторный процессор (подробнее об этом ниже). Идея, насколько я помню, состоит в том, что у вас есть ряд значений, и вы выполняете одни и те же операции, несколько раз, параллельно, для всех них одновременно. Они обычно используются для крупномасштабных математических / физических упражнений, симуляций и графических работ (я думаю, в том числе 3D-графики на ПК / консоли).

Если я правильно помню, в C вы можете поместить несколько операторов в одну «строку кода», например так:

int a, b, c;
a = 1, b = 2, c = 3;

Однако это ничем не отличается от написания:

int a, b, c;
a = 1; b = 2; c = 3;

который в свою очередь идентичен

int a, b, c;
a = 1;
b = 2;
c = 3;

и все это переводит в компилятор одно и то же. Поэтому, хотя один из них использует только одно синтаксическое «утверждение», а два из них написаны в одной строке, все они идентичны, за исключением синтаксиса.

Существуют языки, которые могут генерировать более одного значения за один вызов одного из нормальных базовых элементов языка; например, в Лиспе вы можете использовать maphash для запуска одной и той же функции на каждом элементе хеш-таблицы, и если функция снова записывает данные в хеш-таблицу, то одна «строка кода» записывает много значений. Но это бессмысленная мера, потому что эта строка кода выполняет множество вещей изнутри.

Вероятно, лучшим примером являются определенные модели параллельного программирования. Векторные процессоры предназначены для того, чтобы вы могли запускать одну инструкцию для (4/8/16 / N) разных элементов данных одновременно и параллельно; Вы могли бы осмысленно сказать, что он делает то, о чем вы спрашиваете, но тогда вам нужно научиться кодировать в сборке для векторных машин. Кроме того, некоторые модели параллельного программирования предполагают, что у вас есть один параллельный фрагмент кода, который выполняется одновременно в N потоках, начиная с N различных наборов входных данных и вычисляя правильный вывод для каждого из них. Предполагается, что любая реализация модели способна гарантировать, что различные исполнения «собираются вместе» в определенных точках кода, где все синхронизируется, и они могут читать данные других процессов и действовать на них.

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

4 голосов
/ 24 октября 2009

Если присвоение не происходит внутри базы данных или другого программного обеспечения с поддержкой транзакций, два приведенных вами примера кода , скорее всего, приведут к 100% идентичным инструкциям, выполняемым ЦП .

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

UPDATE:

  1. Просто чтобы прояснить, как отмечали другие, a = b = c = 0; - это просто синтаксический сахар C (и других языков), который в действительности переводится как:

    c = 0;
    b = c;
    a = b;
    
  2. МОГУТ быть языки / рамки, в которых 3 назначения являются «атомарными» в том смысле, что они выполняются одновременно как транзакция, если это то, что вы подразумевали под «1 вызовом». наиболее очевидным примером является SQL, где высказывание UPDATE table SET a=0,b=0,c=0 ... действительно не только гарантирует, что 3 обновления происходят как один «вызов», но и является транзакцией - либо все они обновлены, либо отсутствуют.

1 голос
/ 24 октября 2009

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

Возможно, что умный компилятор сможет перевести: int8 c = 1, c = 2; в одно присваивание int16 (возможно, сохраняя оба значения в одном регистре), если оно было записано для этого. С другой стороны, int16 d = 4; может занять несколько циклов (читай: неатомарное) на 8-битном оборудовании. Пойди разберись.

Да, некоторые процессоры могут изменять две переменные (несколько слотов хранения) в элементарной («одновременной») операции.

Наиболее распространенные из них обеспечивают основу для аппаратно-безопасной синхронизации.

CMPXCNG - Сравнение и обмен

CMPSWP - Сравнить и поменять местами

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

1 голос
/ 24 октября 2009

Не возможно, процессор, но это легко сделать с помощью FPGA.

Например, есть C-подобный язык, называемый Handel C , который используется для разработки ПЛИС. Поскольку код переведен на аппаратное обеспечение , возможен истинный параллелизм на уровне операторов.

Дескриптор C имеет конструкции par и seq , которые определяют, выполняются ли операторы параллельно или последовательно. Время выполнения блока par - это время выполнения самого медленного оператора (или вложенного блока, или вызова), а присвоение переменных занимает 1 такт, поэтому:

// Three assignments in one clock
par
{
   a = 1;
   b = 2;
   c = 3;
}

// Three assignments in three clocks
seq
{
   a = 1;
   b = 2;
   c = 3;
}

Интересной особенностью этого является, например, если у вас есть:

par
{
  a++ ;
  b = a ;
}

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

1 голос
/ 24 октября 2009

Почему бы не поместить значения в массив и использовать memset или макрос ZeroMemory (который использует memset внутри.

1 голос
/ 24 октября 2009

Я думаю, вы можете немного запутаться. Вы даже не можете достичь этого с помощью потоков. Что вы подразумеваете под «вызовом» точно? Одна строка кода? Эта первая строка - просто удобство, предлагаемое во время объявления на многих языках, подобных Си.

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

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

0 голосов
/ 24 октября 2009

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

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

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

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