Презентацию к лекции Вы можете скачать здесь.
Область видимости – один из важнейших атрибутов переменной. Если область видимости ограничена, переменная называется локальной. Если область видимости переменной совпадает с программой, переменная называется глобальной.
В многопоточном программировании область видимости получает дополнительное измерение – видимость между потоками. Исполнение параллельной программы перестаёт быть локальным!
Pro
Использование глобальных переменных позволяет избежать «раздувания» списков параметров. Глобальными объявляются часто используемые параметры.
Contra
Побочные эффекты использования глобальных переменных могут препятствовать эффективной реализации параллелизма.
Пусть два оператора из разных потоков имеют доступ к одной переменной x. Тогда могут существовать 3 типа гонок за данными:
| Оператор 1 | Оператор 2 | Тип «гонок за данными» |
|---|---|---|
| чтение | чтение | отсутствуют |
| чтение | запись | по чтению |
| запись | чтение | по чтению |
| запись | запись | по записи |
Размер машинного слова может влиять на наличие гонок – при работе с упакованными структурами данных. Пример:
struct{
char a;
char b;
} x;
Наличие гонок может зависеть от уровня оптимизации.
Гонки за данными – возникают при одновременном доступе из разных потоков к одной переменной. Отрицательный эффект – утрата детерминизма в поведении программы, утрата корректности. Это происходит, если
Синхронизация доступа к переменной.
Использование локальных относительно потоков переменных.
Гиперобъекты (редукторы) в Intel® Cilk™ Plus – реализуют механизм разрешения гонок за данными.
Гиперобъект (редуктор) – в простейшем случае объект, с которым ассоциированы: значение, начальное значение, функция приведения.
Обращаться с редуктором надо как с объектом. Например, запрещено прямое копирование – результат такого копирования не определён.
При работе с редукторами не надо использовать блокировки => увеличивается производительность.
Редукторы сохраняют последовательную семантику: результат параллельной программы совпадает с результатом последовательной программы.
Редукторы можно использовать не только в циклах.
Переменная может быть описана как редуктор относительно ассоциативной операции (сложение, умножение, логическое И, объединение списков и другие). Требуется также использование соответствующего заголовочного файла. Пример:
#include <cilk/cilk.h>
#include <cilk/reducer_min.h>
template <typename T>
size_t IndexOfMin(T array[], size_t n)
{
cilk::reducer_min_index<size_t, T> r;
cilk_for (int i = 0; i < n; ++i)
r.min_of(i, array[i]);
return r.get_index();
}
Изображение переменной – это её экземпляр. Потоки могут работать с переменной как с обычной нелокальной переменной.
При создании потока он получает собственное изображение переменной. В многопоточном приложении для переменной создаётся набор изображений.
Система времени исполнения Cilk Plus координирует работу с изображениями переменной и объединяет их в точке объединения потоков (отсюда название - редукторы).
Когда остаётся единственное изображение, оно устойчиво и значение переменной может быть извлечено из этого изображения.
Редуктор суммирования:
Если в процессе выполнения Cilk-программы не происходит захвата работы, редуктор ведёт себя как обычная переменная.
Если происходит захват работы, потомок и продолжение получают собственные изображения.
Такую семантику иногда называют «ленивой».
#include <cilk/cilk.h>
#include <cilk/reducer_opadd.h>
class CilkForSum : public Sum {
public:
virtual double FindSum(SimpleArray data) {
cilk::reducer_opadd<double> result(0);
cilk_for(int i=0; i<data.GetSize(); i++)
result += operation(data[i]);
return result.get_value();
}
};
| Редуктор/заголовок | Инициализация | Описание |
|---|---|---|
reducer_list_append <cilk/reducer_list.h> |
Пустой список | Объединение списков добавлением в конец |
reducer_list_prepend <cilk/reducer_list.h> |
Пустой список | Объединение списков добавлением в начало |
reducer_max <cilk/reducer_max.h> |
Аргумент конструктора | Нахождение максимального значения |
reducer_max_index <cilk/reducer_max.h> |
Аргумент конструктора | Нахождение максимального значения и его индекса в массиве |
reducer_min <cilk/reducer_min.h> |
Аргумент конструктора | Нахождение минимального значения |
reducer_min_index <cilk/reducer_min.h> |
Аргумент конструктора | Нахождение минимального значения и его индекса в массиве |
reducer_opadd <cilk/reducer_opadd.h> |
0 | Суммирование |
reducer_opand <cilk/reducer_opand.h> |
1/true | Логическое И |
reducer_opor <cilk/reducer_opor.h> |
0/false | Логическое ИЛИ |
reducer_opxor <cilk/reducer_opxor.h> |
0/false | Логическое исключающее ИЛИ |
reducer_ostream <cilk/reducer_ostream.h> |
Аргумент конструктора | Параллельный поток вывода |
reducer_basic_string <cilk/reducer_string.h> |
Пустая строка | Создание строки с помощью конкатенации |
reducer_string <cilk/reducer_string.h> |
Пустая строка | Создание строки с помощью конкатенации |
reducer_wstring <cilk/reducer_string.h> |
Пустая строка | Создание строки с помощью конкатенации |
reducer.h reducer_list.h reducer_max.h reducer_min.h reducer_opadd.h reducer_opand.h reducer_opor.h reducer_opxor.h reducer_ostream.h reducer_string.h
cilk::reducer_opadd<float> sum;
void f( int m ) {
sum += m;
}
float g() {
cilk_spawn f(1);
f(2);
cilk_sync;
return sum.get_value();
}
Еще один пример:
cilk::reducer_opadd<float> sum = 0; ... cilk_for( size_t i=1; i<n; ++i ) sum += f(i); ... = sum.get_value();
Пример
#include <cilk/cilk.h>
#include <cilk/reducer_opadd.h>
#include <iostream>
#include <math.h>
…
// CilkForSum class uses cilk_for keyword to compute the sum
in parallel
// cilk::reducer_opadd class is used for sync
class CilkForSum : public Sum {
public:
virtual double FindSum(SimpleArray data) {
cilk::reducer_opadd<double> result(0);
cilk_for(int i=0; i<data.GetSize(); i++)
result += operation(data[i]);
return result.get_value();
}
};
Редуктор, определённый пользователем, состоит из 4-х логических частей:
get_value() возвращает значение.
#include <cilk/reducer.h>
class point
{
// Здесь – определение класса point
};
class point_holder
{
struct Monoid: cilk::monoid_base<point>
{
static void reduce (point *left, point *right) {}
};
private:
cilk::reducer<Monoid> imp_;
public:
point_holder() : imp_() {}
void set(int x, int y) {
point p = imp_.view();
p.set(x, y);
}
bool is_valid() { return imp_.view().is_valid(); }
int x() { return imp_.view().x(); }
int y() { return imp_.view().y(); }
};
Cilk Plus позволяет выявлять гонки за данными независимо от числа потоков, при умеренных накладных расходах (памяти и процессорного времени).
Cilkscreen – инструмент выявления гонок за данными.
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.