Студопедия Главная Случайная страница Обратная связь

Разделы: Автомобили Астрономия Биология География Дом и сад Другие языки Другое Информатика История Культура Литература Логика Математика Медицина Металлургия Механика Образование Охрана труда Педагогика Политика Право Психология Религия Риторика Социология Спорт Строительство Технология Туризм Физика Философия Финансы Химия Черчение Экология Экономика Электроника

Пример программы





Ниже мы подробно рассмотрим программу, запускающую сложение матриц на графическом процессоре. Текст программы написан на языке C#. Мы не будем исчерпывающе комментировать синтаксис этого языка, но детально прокомментируем операции, исполняемые над данными для видеокарты.

· Подключение необходимых библиотек. Используется стандартная библиотека System, а кроме того – библиотека Microsoft.Xna.Framework, упрощающая подготовку данных для графического процессора. Раздел этой библиотеки Microsoft.Xna.Framework.Graphics подключаем отдель­но, чтобы сократить в тексте программы описание доступа к ресурсам этого раздела.

using System;

using Microsoft.Xna.Framework;

using Microsoft.Xna.Framework.Graphics;

 

public class GPGPU: Microsoft.Xna.Framework.Game

{

· Описание переменных, используемых программой

/* Задаётся размер матрицы, количество элементов в строке/столбце */

int size = 3;

/* Описываем переменную graphics класса GraphicsDeviceManager и затем инициализируем эту переменную операцией graphics = new GraphicsDeviceManager(this). Эта переменная будет обеспечивать доступ к процедурам для управления графическим процессором из библиотеки Microsoft.Xna.Framework */

GraphicsDeviceManager graphics;

· Стандартные процедуры, реализующие исполнение программы на C#

/* Ниже описаны процедуры, которые будут последовательно испол­нены сразу после запуска программы. Процедуры Main и Initialize являются стандартными для проектов на C#. Внутри процедуры Initialize находится вызов процедуры MatrixSum(), которая и осуществляет суммирование матриц на графическом процессоре. */

static void Main(string[] args) { using (GPGPU game = new GPGPU()) game.Run(); }

public GPGPU() { graphics = new GraphicsDeviceManager(this); }

protected override void Initialize()

{

base.Initialize();

MatrixSum();

Exit();

}

 

· Процедура, суммирующая матрицы с использованием GPU

private void MatrixSum()

{

/* Выше была введена переменная graphics класса GraphicsDevice­Manager. В этом классе есть нужный нам подкласс GraphicsDevice. Создаём переменную gpu этого подкласса */

GraphicsDevice gpu = graphics.GraphicsDevice;

· Выделение памяти для рендер-цели

/* Созданная в начале программы переменная size = 3 задаёт размеры матриц (3´ 3), которые мы будем складывать. Теперь создается рендер-цель – массив 3´ 3, в который будет выво­диться результат расчетов. Соответствующая переменная называется tex_target. Она является не простым массивом 3´ 3, а принадлежит к классу RenderTarget2D из библиотеки Microsoft.­Xna.­Framework. Кроме самого массива, в объектах этого класса хранятся некоторые дополнительные параметры, в частности – указатель на переменную gpu, который задаёт конкретную видеокарту, для которой создаётся рендер-цель. */

RenderTarget2D tex_target = new RenderTarget2D(gpu, size, size, 1, SurfaceFormat.Single);

· Выделение памяти для текстур с исходными данными

/* Создаются текстуры, – массивы размера size*size, - в которых будут храниться исходные матрицы. Как и рендер-цель, соответст­вующие переменные являются не простыми массивами, а принад­лежат к более сложному классу Texture2D, в объектах которого, кроме самих массивов, хранятся дополнительные параметры. Как и выше, значения этих параметров устанавливаются при создании новой переменной класса, строкой new Texture2D(gpu, size, size, 1, ResourceUsage.­Dynamic, SurfaceFormat.Single, ResourceManage­ment­Mode.Manual), значениями внутри скобок. */

Texture2D tex_matrix1 = new Texture2D(gpu, size, size, 1, ResourceUsage.Dynamic, SurfaceFormat.Single, ResourceManagement­Mode.Manual);

Texture2D tex_matrix2 = new Texture2D(gpu, size, size, 1, Resource­Usage.Dynamic, SurfaceFormat.Single, ResourceManagement­Mode.­Manual);

· Заполнение массивов исходных данных конкретными значениями

/* Теперь, задаём конкретные значения элементов исходных матриц. Сначала эти значения записываются в одномерные массивы matrix1 и matrix2 размеров size * size. Элементы a ij и b ij после преобразования матриц к одномерным массивам будут иметь номера j * size + i. Затем, мы копируем созданные массивы в текстуры класса Texture2D tex_matrix1 и tex_matrix2 операциями tex_matrix1.­SetData< float> (matrix1) и tex_matrix2.SetData< float> ­(matrix2). */

float[] matrix1 = new float[size * size], matrix2 = new float[size * size];

for (int j = 0; j < size; j++)

for (int i = 0; i < size; i++)

{

matrix1[j * size + i] = j * size + i;

matrix2[j * size + i] = i * size + j;

}

tex_matrix1.SetData< float> (matrix1);

tex_matrix2.SetData< float> (matrix2);

· Установление соответствия между целочисленными индексами элементов матриц и текстурными координатами этих элементов

/*Следующая задача – установление соответствия между целочисленными индексами элементов матриц 3´ 3 и текстурными координатами этих же элементов внутри квадрата (-1; -1)-(1; 1), или quad’а, которыми будет оперировать графический процессор, а также внутри квадрата (0; 0)-(1; 1), в который отображается массив результатов (рендер-цель). Для этого достаточно задать соответствие между индексами «крайних» элементов матриц и координатами вершин квадрата. Соответствие это показано в таблице 5.1. При необходимости рассмотрения матриц других размеров, знаменатель 6 нужно заменить на значение 2*size.

Таблица 5.1

Соответствие между координатами вершин quad’а (-1; -1)-(1; 1) и координатами элементов складываемых матриц

Вершины quad’а Координаты элементов рендер-цели
(-1; 1) (1/6; 1/6)
(-1; -1) (1/6; 1+1/6)
(1; 1) (1+1/6; 1/6)
(1; -1) (1+1/6; 1+1/6)

 

Метод определения координат элементов проиллюстрирован также на рис. 5.2. Видно, что приведённые формулы действительно обеспечивают попадание эле­ментов массива 3´ 3 в необходимые области. Учтён также тот факт, что ось Y на экране (и в рендер цели) направлена сверху вниз.

Третья пространстваенная координата во входных данных у нас не используется, поэтому в конструкторах вида Vector3(-1, 1, 0) третья координата равна нулю, тогда как первые два значения задают координаты вершин quad’а */

float dx = 0.5f / size, dy = 0.5f / size; // смещения для адресации центров текселей

VertexPositionTexture[] v = new VertexPositionTexture[] {

new VertexPositionTexture(new Vector3(-1, 1, 0), new Vector2(0 + dx, 0 + dy)),

new VertexPositionTexture(new Vector3(-1, -1, 0), new Vector2(0 + dx, 1 + dy)),

new VertexPositionTexture(new Vector3(1, 1, 0), new Vector2(1 + dx, 0 + dy)),

new VertexPositionTexture(new Vector3(1, -1, 0), new Vector2(1 + dx, 1 + dy))

};

/* Следующей, стандартной, строкой выделяется область памяти для хранения координат вешин quad’а. Этих вершин 4, чем и обусловлен размер 4 * VertexPositionTexture.SizeInBytes */

VertexBuffer quad = new VertexBuffer(gpu, 4 * VertexPosition­Texture.SizeInBytes, ResourceUsage.None, ResourceManagementMode.­Automatic);

quad.SetData< VertexPositionTexture> (v);

VertexDeclaration quadVertexDeclaration = new VertexDeclaration­(gpu, VertexPositionTexture.VertexElements);

· Компилирование эффектов, содержащих шейдеры

/* В библиотеку Microsoft.Xna.Framework встроен компилятор текстовых файлов, содержащих шейдеры для графического процессора, таких как sum.fx (начало примера и Приложение 1). Следующая строка компилирует файл sum.fx и запи­сывает полученную программу (в машинных кодах) в область оперативной памяти, на которую указывает переменная e типа CompiledEffect. */

CompiledEffect e = Effect.CompileEffectFromFile(" sum.fx", null, null, CompilerOptions.None, TargetPlatform.Windows);

/* Проверка успешности компиляции */

if (! e.Success) throw new Exception(e.ErrorsAndWarnings);

· Выбор шейдера, который будет исполняться

/* Создаётся новая переменная, описывающая эффект, который будет исполняться на графическом процессоре. В качестве кода эффекта выбирается откомпилированная программа, на которую указывает переменная e. */

Effect fx = new Effect(gpu, e.GetEffectCode(), CompilerOptions.None, null);

/* В качестве запускаемой на видеокарте процедуры выбирается техника sum из файла sum.fx (описана выше) */

fx.CurrentTechnique = fx.Techniques[" sum" ];

· Копирование исходных данных в видеопамять, доступную графическому процессору

/* В качестве исходных данных передаём эффекту fx текстуры с исходными данными tex_matrix1 и tex_matrix2, которые мы уже создали в начале программы: */

fx.Parameters[" tex_matrix1" ].SetValue(tex_matrix1);

fx.Parameters[" tex_matrix2" ].SetValue(tex_matrix2);

/* Задаем выходные параметры: quad и рендер-цель: */

gpu.Vertices[0].SetSource(quad, 0, VertexPositionTexture.SizeInBytes);

gpu.VertexDeclaration = quadVertexDeclaration;

gpu.SetRenderTarget(0, tex_target);

· Исполнение шейдера на графическом процессоре

fx.Begin();

fx.CurrentTechnique.Passes[" sum" ].Begin();

gpu.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);

fx.CurrentTechnique.Passes[" sum" ].End();

fx.End();

· Получение результата из рендер-цели и сохранение его в текстовом файле

/* Копирование массива результатов из видеопамяти в оперативную память, доступную центральному процессору */

gpu.ResolveRenderTarget(0);

/* Создаём текстовый файл для записи результата */

using (System.IO.StreamWriter w = new System.IO.StreamWriter­(" results.txt"))

{

/* Создаём одномерный массив, в который будут скопированы данные из рендер-цели, для дальнейшей обработки центральным процессором */

float[] matrix3 = new float[size * size];

/* Копирование данных из рендер цели в массив matrix3. Аргумент < float> означает, что данные будут скопированы в виде скалярных чисел одинарной точности */

tex_target.GetTexture().GetData< float> (matrix3);

/* Запись данных из массива matrix3 в текстовый файл */

for (int j = 0; j < size; j++)

{

for (int i = 0; i < size; i++) w.Write(" \t{0}", matrix3[j * size + i]);

w.WriteLine();

}

}}}

 







Дата добавления: 2014-12-06; просмотров: 684. Нарушение авторских прав; Мы поможем в написании вашей работы!




Аальтернативная стоимость. Кривая производственных возможностей В экономике Буридании есть 100 ед. труда с производительностью 4 м ткани или 2 кг мяса...


Вычисление основной дактилоскопической формулы Вычислением основной дактоформулы обычно занимается следователь. Для этого все десять пальцев разбиваются на пять пар...


Расчетные и графические задания Равновесный объем - это объем, определяемый равенством спроса и предложения...


Кардиналистский и ординалистский подходы Кардиналистский (количественный подход) к анализу полезности основан на представлении о возможности измерения различных благ в условных единицах полезности...

Меры безопасности при обращении с оружием и боеприпасами 64. Получение (сдача) оружия и боеприпасов для проведения стрельб осуществляется в установленном порядке[1]. 65. Безопасность при проведении стрельб обеспечивается...

Весы настольные циферблатные Весы настольные циферблатные РН-10Ц13 (рис.3.1) выпускаются с наибольшими пределами взвешивания 2...

Хронометражно-табличная методика определения суточного расхода энергии студента Цель: познакомиться с хронометражно-табличным методом опреде­ления суточного расхода энергии...

Понятие и структура педагогической техники Педагогическая техника представляет собой важнейший инструмент педагогической технологии, поскольку обеспечивает учителю и воспитателю возможность добиться гармонии между содержанием профессиональной деятельности и ее внешним проявлением...

Репродуктивное здоровье, как составляющая часть здоровья человека и общества   Репродуктивное здоровье – это состояние полного физического, умственного и социального благополучия при отсутствии заболеваний репродуктивной системы на всех этапах жизни человека...

Случайной величины Плотностью распределения вероятностей непрерывной случайной величины Х называют функцию f(x) – первую производную от функции распределения F(x): Понятие плотность распределения вероятностей случайной величины Х для дискретной величины неприменима...

Studopedia.info - Студопедия - 2014-2026 год . (0.011 сек.) русская версия | украинская версия