По умолчанию, вновь созданный процессорный объект размещается на том же самом процессоре, на котором ведется разработка программы. Альтернативное расположение может быть задано новому оператору параметром размещения. В C++ этот параметр применяется для размещения объекта в пространстве памяти. В CC++ он может использоваться также и для размещения процессорного объекта в пространстве процессоров. (Параметр размещения может также использоваться для точного описания места расположения кода процессорного объекта в файловой системе компьютера.).
Местоположение определяется обусловленной зависимостью от класса, названного proc_t. Конструкторы функций proc_t и node_t, определенные в библиотеке CC++, используются для создания структуры размещения с точно установленным именем процессора. Пример их использования показан в следующем кодовом фрагменте. Здесь, в классе MyClass, создается новый процессорный объект location на процессоре с именем mymachine:
MyClass *global G;
proc_t location(node_t("mymachine"));
G = new (location) MyClass;
Оператор new создает новый процессорный объект G со свойствами объекта location класса MyClass. Процессорный объект location ключевыми словами proc_t и node_t привязан к процессору mymachine. Процессорный объектG наследует эту связь. Чтобы объектG расположить на другом процессоре, потребуется только одно изменение на второй строчке кодового фрагмента, например, так, как показано ниже:
proc_t location(node_t("yourmachine"));
В следующем кодовом фрагменте создается 32 процессорных объекта. Каждый из них размещается на различных процессорах (узлах) многопроцессорной вычислительной системы с названиями процессоров соответственно sp#0, sp#1, ..., sp#31. Ключевое слово parfor используется для одновременного создания этих процессорных объектов.
MyClass *global G[32];
parfor (int i=0; i<31; i++)
{
char node_name[256];
sprintf(node_name,"sp#%",i)
proc_t location(node_t(node_name));
G[i] = new (location) MyClass;
}
Приведенный код прост, однако он плох тем, что в выполняемую программу внедряется информация об окружающей вычислительной среде. Лучшим подходом является тот, в котором отображения формируются в отдельном классе, как в классе Mapping, описанном в тексте 3.8. В этом классе формируется две частные переменные P и proc_names, которые представляют необходимую вычислительную среду для выполнения программы: число процессоров и список их имен. Функция-член initmap используется для инициализации этих переменных. Две дополнительные функции-члены, processor и random_p, возвращают proc_t объект, отображающий i-тый процессор и случайно выбранный процессор соответственно. Наконец, две, опущенные для краткости, функции передачи данных с упаковкой и распаковкой взаимно однозначно свяжут список процессоров с отображаемыми объектами. Каждое отображение передается параметром, когда создается новый процессорный объект. Использование класса Mapping проиллюстрировано в следующем примере.
classMapping // Формирование списка имен процессоров
{
friend CCVoid& operator<<(CCVoid&, const Mapping&);
friend CCVoid& operator>>(CCVoid&, Mapping&);
public:
proc_tprocessor(int); // Доступ к очередному процессору.
proc_trandom_p(); // Доступ к случайному процессору.
voidinitmap(char **); // Активация процессорных имен.
private:
intP; // Число процессоров
char *proc_names[]; // Список процессорных имен
};
proc_t Mapping::processor(int i)
{ // Определение функции отображения очередного процессора
return(proc_t(node_t(proc_names[i%])));
}
proc_t Mapping::random_p()
{ // Определение функции отображения случайного процессора.
return processor(drand48()*((float) P));
}
void Mapping::initmap(char *plist[])
{ // Определение функции создания списка процессорных имен.
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.