QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович
cout << "evaluation time: " << (double)t / 1.E9
<< " sec." << endl;
return EXIT_SUCCESS;
}
Перед нами простейшая последовательная программа, которая массированно читает свою базу данных и изредка ее модифицирует. Для выполнения реальных операций чтения/записи данных программе необходимо выполнять некоторые достаточно продолжительные операции. В приведенном коде эти операции имитируются задержками delay(WRITE_DELAY)и delay(READ_DELAY).
Возникает совершенно естественное желание преобразовать последовательные запросы к данным в параллельные ( файл sy11.cc). Для этого преобразуем структуру списка элементов, с которым работаем:
class dbase : public list<element> {
static const int READ_DELAY = 1, WRITE_DELAY = 2;
pthread_mutex_t loc;
public:
dbase(void) { pthread_mutex_init(&loc, NULL); }
~dbase(void) { pthread_mutex_destroy(&loc); }
void add(const elements e) {
pthread_mutex_lock(&loc);
int pos = size() * rand() / RAND_MAX;
list<element>::iterator p = begin();
for (int i = 0; i < pos; i++) p++;
insert(p, e);
delay(WRITE_DELAY);
pthread_mutex_unlock(&loc);
}
int pos(const elements e) {
int n = 0;
pthread_mutex_lock(&loc);
for (list<element>::iterator i = begin(); i != end(); i++, n++)
if (*i == e) {
delay(READ_DELAY);
break;
}
pthread_mutex_unlock(&loc);
if (n == size()) n = -1;
return n;
}
} data;
А в вызывающей программе цикл запросов к данным преобразуем в:
pthread_t *h = new pthread_t[n];
uint64_t t = ClockCycles();
for (int i = 0; i < n; i++) {
element e = erand(n);
pthread_create(h + i, NULL, wrand(p) ? add : pos, (void*)e);
}
for (int i = 0; i < n; i++)
pthread_join(h[i], NULL);
t = ((ClockCycles() - t) * 1000000000) / cps;
delete h;
А используемые этим фрагментом функции потоков определим как:
static void* add(void* par) { data.add((element)par); }
static void* pos(void* par) { data.pos((element)par); }
Совершенно естественно, что список элементов, из которого мы извлекаем данные (и куда изредка помещаем новые), должен защищаться как при модификации, так и при считывании (во избежание их одновременной модификации «со стороны»). Понятно, что в представленном решении мы чересчур перестраховались: во время считывания мы должны защищаться от потенциальной одновременной модификации, но нет необходимости защищать структуру данных от параллельного считывания. Поэтому переопределим структуру данных ( файл sy12.cc), используя блокировку чтения/записи, оставив все прочее без изменений:
class dbase : public list<element> {
static const int READ_DELAY = 1, WRITE_DELAY = 2;
pthread_rwlock_t loc;
public:
dbase(void) { pthread_rwlock_init(&loc, NULL); }
~dbase(void) { pthread_rwlock_destroy(&loc); }
void add(const elements e) {
pthread_rwlock_wrlock(&loc);
int pos = size() * rand() / RAND_MAX;
list<element>::iterator p = begin();
for (int i = 0; i < pos; i++) p++;
insert(p, e);
delay(WRITE_DELAY);
pthread_rwlock_unlock(&loc);
}
int pos(const elements e) {
int n = 0;
pthread_rwlock_rdlock(&loc);
for (list<element>::iterator i = begin(); i != end(); i++, n++)
if (*i == e) {
delay(READ_DELAY);
break;
}
pthread_rwlock_unlock(&loc);
if (n == size()) n = -1;
return n;
}
} data;
А теперь пришло время сравнить варианты:
# nice -n-19 sy10 500 .2
evaluation time: 1.2296 sec.
# nice -n-19 sy11 500 .2
evaluation time: 1.24973 sec.
# nice -n-19 sy12 500 .2
evaluation time: 0.440904 sec.
При «жесткой» блокировке мы не получаем никакого выигрыша за счет параллельного выполнения запросов к данным, а при использовании блокировки чтения/записи — 3-кратный выигрыш. Проделаем то же самое, но в условиях гораздо меньшей интенсивности обновления данных относительно общего потока запросов:
# nice -n-19 sy10 500 .02
Откройте для себя мир чтения на siteknig.com - месте, где каждая книга оживает прямо в браузере. Здесь вас уже ждёт произведение QNX/UNIX: Анатомия параллелизма - Цилюрик Олег Иванович, относящееся к жанру Интернет. Никаких регистраций, никаких преград - только вы и история, доступная в полном формате. Наш литературный портал создан для тех, кто любит комфорт: хотите читать с телефона - пожалуйста; предпочитаете ноутбук - идеально! Все книги открываются моментально и представлены полностью, без сокращений и скрытых страниц. Каталог жанров поможет вам быстро найти что-то по настроению: увлекательный роман, динамичное фэнтези, глубокую классику или лёгкое чтение перед сном. Мы ежедневно расширяем библиотеку, добавляя новые произведения, чтобы вам всегда было что открыть "на потом". Сегодня на siteknig.com доступно более 200000 книг - и каждая готова стать вашей новой любимой. Просто выбирайте, открывайте и наслаждайтесь чтением там, где вам удобно.


