Может ли компилятор оптимизировать несвязанные команды для выполнения с разными ядрами? - PullRequest
0 голосов
/ 20 сентября 2018

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

Например:

...
for (...) 
{
    //...
    int a = a1+a2;
    int b = b1+b2;
    int c = c1+c2;
    int d = d1+d2;
    //...
}
...

Может ли случиться так, что с точки зрения оптимизации может быть изменен не только порядок выполнения, но иколичество ядер?Есть ли в компиляторе какие-либо ограничения в стандарте?

UPD: я не спрашиваю, как распараллелить код, я спрашиваю, не был ли он распараллелен явно, может ли он все еще распараллеливаться компилятором?

Ответы [ 2 ]

0 голосов
/ 20 сентября 2018

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

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

Различные конвейеры ваших инструкций будут выполняться параллельно в конвейерах (современные процессоры x86)имеет более десятка стадий конвейера) и, возможно, разные инструкции будут выполняться параллельно в разных ALUS (современные процессоры x86 имеют около 5 ALU на ядро).

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

1) ну, на самом деле гиперпоточность - это.

2) Как указывает MSalters:

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

Все это косвенно влияет на выполнение для получения выгодыаппаратная архитектура, нет явных инструкций или объявлений.

0 голосов
/ 20 сентября 2018

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

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

...