Введение в QNX/Neutrino 2. Руководство по программированию приложений реального времени в QNX Realtime Platform | страница 38



. Это обстоятельство (независимость строк растра) автоматически приводит к программированию данной задачи как многопоточной.

Ниже приведен однопоточный вариант:

>int main (int argc, char **argv) {

> int x1;


> ... // Выполнить инициализации


> for (x1 = 0; x1 < num_x_lines; x1++) {

>  do_one_line(x1);

> }


> ... // Вывести результат


>}

Здесь мы видим, что программа итеративно по всем значениям рассчитает необходимые растровые строки.

В многопроцессорных системах эта программа будет использовать только один из процессоров. Почему? Потому что мы не указали операционной системе выполнять что-либо параллельно. Операционная система не настолько умна, чтобы посмотреть на программу и сказать: «Эй, секундочку! У нас ее 4 процессора, и похоже, что у нас тут несколько независимых потоков управления. Запущу-ка я это на всех 4 процессорах сразу!»

Так что это дело разработчика (ваше дело!) — сообщить QNX/Neutrino, какие разделы программы следует выполнять параллельно. Проще всего это можно было бы сделать так:

>int main (int argc, char **argv) {

> int x1;


> ... // Выполнить инициализации


> for (x1 = 0; x1 < num_x_lines; x1++) {

>  pthread_create(NULL, NULL, do_one_line, (void*)x1);

> }


> ... // Вывести результат


>}

С таким упрощением связано множество проблем. Первая из них (и самая незначительная) состоит в том, что функцию do_one_line() придется модифицировать так, чтобы она могла в качестве своего аргумента принимать значение типа >void* вместо >int. Это можно легко исправить с помощью оператора приведения типа (typecast).

Вторая проблема несколько сложнее. Скажем, что разрешающая способность дисплея, для которой вы рассчитывали картинку, была равна 1280×1024. Нам пришлось бы создать 1280 потоков! В общем-то, для QNX/Neutrino это не проблема — QNX/Neutrino позволяет создавать до 32767 потоков в одном процессе! Однако, каждый поток должен иметь свой уникальный стек. Если ваш стек имеет разумный размер (скажем 8 Кб), эта программа израсходует под стек 1280×8 Кб (10 мегабайт!) ОЗУ. И ради чего? В вашей системе есть только 4 процессора. Это означает, что только 4 из этих 1280 потоков будут работать одновременно, а другие 1276 потоков будут ожидать доступа к процессору. (В действительности, в данном случае пространство под стек будет выделяться только по мере необходимости. Но тем не менее, это все равно расходование ресурсов впустую — есть ведь еще и другие издержки.)

Более красивым способом решения этой задачи было бы разбить ее на 4 части (по одной подзадаче на каждый процессор), и обрабатывать каждую часть как отдельный поток: