Олег Цилюрик - QNX/UNIX: Анатомия параллелизма
int fd = open(PATH, O_RDONLY);
if (fd < 0) exit("server not found");
// читаем его параметры
if (read(fd, &data, sizeof(result)) == -1)
exit("parameter block read");
cout << ", server = " << data.cps << endl;
// определяем дескриптор сетевого узла
int32_t node = netmgr_strtond(PATH, NULL);
if (node == -1 && fd > 0 && errno == ENOENT)
node = ND_LOCAL_NODE;
// по адресным данным, полученным ранее по read(), создаем
// канал для прямого обмена сообщениями с тем же процессом
int coid = ConnectAttach(node, data.pid, data.chid, _NTO_SIDE_CHANNEL, 0);
if (coid < 0) exit("connect to message channel");
// динамически готовим код команды devctl():
unsigned int DCTL = (blk << 16) + DCMD_SRR;
cout << " . . . . . waiting ^C . . . . . " << flush;
// устанавливается реакция на пользовательский ^C
signal(SIGINT, trap);
uint64_t num = 0;
uint8_t *bufin = new uint8_t[blk], *bufou = new uint8_t[blk];
uint64_t tim = ClockCycles();
// в зависимости от выбранного механизма передаем с его помощью данные
if (lowlvl)
while (true) {
if (MsgSend(coid, bufou, blk, bufin, blk) == -1)
exit("exchange data with channel");
num++;
if (!conti) break;
}
else {
while (true) {
if (devctl(fd, DCTL, bufou, blk, NULL) != EOK)
exit("DEVCTL error");
num++;
if (!conti) break;
}
}
tim = ClockCycles() - tim;
cout << 'r' << (lowlvl ? "message exchange:" : "manager exchange:") <<
" number = " << num << "; stream = "
<< (double)num * blk / ((double)tim / (double)cps) / 1E6 * 8 <<
" Mbit/sec" << endl;
ConnectDetach(coid);
close(fd);
delete [] bufin;
delete [] bufou;
return EXIT_SUCCESS;
}
В результате мы получаем оценки максимальной плотности потока обмена, достижимые в выбранных (при помощи ключей) условиях на данном процессоре:
# clr -b1
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 1 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
message exchange: number = 906400; stream = 1.54088 Mbit/sec
# clr -b1 -d
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 1
bytes CPU speed [c.p.s.]: client = 534639500, server = 534639500
manager exchange, number = 335725; stream = 0.617311 Mbit/sec
# clr -b10
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 10 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
message exchange: number = 1119211; stream = 15.0758 Mbit/sec
# clr -bl0 -d
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 10 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
manager exchange: number = 316948; stream = 6.1421 Mbit/sec
# clr -b100
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 100 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
message exchange: number = 729460; stream = 122.617 Mbit/sec
# clr -b100 -d
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 100 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
manager exchange: number = 318435, stream = 57.3215 Mbit/sec
# clr -b1000
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 1000 bytes
CPU speed [с.p.s.]: client = 534639500, server = 534639500
message exchange: number = 823535; stream = 1054.65 Mbit/sec
# clr -b1000 -d
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 1000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
manager exchange: number = 367712; stream = 493.455 Mbit/sec
# clr -b10000
SRR repeater: vers. 1 03
server path: /dev/srr, block size = 10000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
message exchange number = 196479, stream = 2861.27 Mbit/sec
# clr -b10000 -d
SRR repeater: vers. 1.03
server path: /dev/srr, block size = 10000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 534639500
manager exchange: number = 141593, stream = 2487.18 Mbit/sec
Цифры достаточно интересные, для того чтобы рассмотреть их детальнее:
• При непрерывном потоке обмена очень короткими сообщениями (1 байт) плотность информационного потока падает до смехотворно низкой величины — 192 Кбайт/сек для обмена сообщениями и 77 Кбайт/сек для обмена с менеджером ресурса.
• При размере блока данных, передаваемого за один обмен, порядка нескольких килобайт разница скоростей информационных потоков для обмена сообщениями и менеджера ресурса практически нивелируется.
• При промежуточных размерах блока данных (от нескольких десятков до сот байт) обмен сообщениями обеспечивает плотность информационного потока до двух раз выше.
Естественно, поскольку мы рассматриваем чисто программные реализации обмена, абсолютные численные значения будут прямо пропорционально зависеть от скорости процессора (представленные результаты соответствуют процессору 533 МГц). На рис. 5.2 показана динамика загрузки процессора при работе тестовых приложений для случая локального размещения клиента и сервера. Хорошо видно, что в периоды выполнения программы clr загрузка процессора подскакивает до 100% — совместной активностью клиент и сервер забирают весь ресурс процессора.
Рис. 5.2. Динамика загрузки процессора при локальном взаимодействии клиента с сервером
Далее посмотрим выполнение той же пары приложений, но уже при разнесении их между раздельными узлами сети:
# clr -nrtp -b1
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 1 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
message exchange: number = 5049, stream = 0.00670981 Mbit/sec
# clr -nrtp -b1 -d
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 1 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
manager exchange: number = 4824; stream = 0.00598806 Mbit/sec
# clr -nrtp -b10
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 10 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
message exchange number = 3885; stream = 0.0651842 Mbit/sec
# clr -nrtp -b10 -d
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 10 bytes
CPU speed [c.p.s ]: client = 534639500, server = 451163200
manager exchange: number = 3102, stream = 0.0557978 Mbit/sec
# clr -nrtp -b100
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 100 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
message exchange: number = 3347, stream = 0.507917 Mbit/sec
При взаимодействии клиента с сервером по сети в тех же условиях, что и на рис. 5.2, клиент уже не загружает процессор более чем на 50% (рис. 5.3). Если организовать обмен клиента с сервером в несколько потоков (2-3), то при максимальной загрузке процессора можно увеличить плотность потока еще вдвое.
Рис. 5.3. Загрузка процессора клиента при сетевом взаимодействии клиента с сервером
# clr -nrtp -b100 -d
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 100 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
manager exchange: number = 2167; stream = 0.480264 Mbit/sec
# clr -nrtp -b1000
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 1000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
message exchange: number = 1400; stream = 2.0555 Mbit/sec
# clr -nrtp -b1000 -d
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 1000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
manager exchange: number = 1626; stream = 2.00553 Mbit/sec
# clr -nrtp -b10000
SRR repeater: vers. 1.03
server path: /net/rtp/dev/srr, block size = 10000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
message exchange: number = 366; stream = 4.73793 Mbit/sec
# clr -nrtp -b10000 -d
SRR repeater: vers 1.03
server path: /net/rtp/dev/srr, block size = 10000 bytes
CPU speed [c.p.s.]: client = 534639500, server = 451163200
manager exchange: number = 440; stream = 4.39515 Mbit/sec
При взаимодействии по сети разница между реализациями обмена сообщениями и менеджера ресурсов не так заметна. Это и понятно: плотность потока обмена начинает ограничиваться в первую очередь задержками физической среды передачи.
Обратите внимание, что при больших блоках передаваемых данных (10 Кбайт) скорость информационного канала (4.395–4.738*2, учитывая что ретрансляция ведется в двух направлениях) сильно приближается к физической пропускной способности канала (10 Мбит/сек, как уже отмечалось выше), что попутно говорит о весьма высокой эффективности реализации обмена протоколами сети QNET.
Что же в итоге?
В итоге, имеющие место споры приверженцев организации обмена сообщениями и сторонников написания менеджеров ресурсов оказываются бессмысленными. В системах, обслуживающих максимально плотные потоки непрерывной входной информации (классическая постановка задачи для телефонных коммутаторов), реализация обмена сообщениями может оказаться заметно продуктивнее. С другой стороны, в системах с эпизодическим обслуживанием запросов (радиолокационные системы, системы управления технологическим оборудованием) реализация менеджера ресурса может привести к тому, что система станет намного более простой и гибкой в эксплуатации.