 | Глава 4. Базовая структура ALF-приложения
Базовая структура ALF-приложения изображена на рис. 2. Процесс на основном процессоре организован следующим образом:
- Инициализируется среда исполнения ALF.
- Создается вычислительное задание.
- После того как задача создана, можно начинать добавлять рабочие блоки к рабочей очереди задания.
- После завершения задачи среда исполнения ALF выгружается из памяти, чтобы высвободить выделенные ресурсы.
Процесс на акселераторе организован следующим образом:
- Созданный экземпляр задания ожидает рабочих блоков, которые добавляются к рабочей очереди.
- Для каждого рабочего блока вызывается функция
alf_accel_comp_kernel. - Если атрибуту
ALF_TASK_DESC_PARTITION_ON_ACCEL дескриптора задания при создании последнего было присвоено значение 1, то перед вызовом вычислительного ядра вызывается функция alf_accel_input_dtl_prepare, а после завершения работы вычислительного ядра вызывается функция alf_accel_output_dtl_prepare.
Примеры ALF-приложений, включающие образцы исходного текста, приведены в Приложении Б («Примеры») на стр. 123.
Рис. 2. Структура и диаграмма выполнения ALF-приложения
Простой пример
В нижеприведенном примере рассматривается простое ALF-приложение. Основная программа инициализирует среду исполнения ALF, создает дескриптор задания, ассоциированное с ним задание, добавляет один рабочий блок в рабочую очередь задания, ожидает завершения задания и в конце завершает работу среды исполнения ALF.
Вычислительное ядро, исполняемое акселератором, выводит текст «Hello World» на стандартное устройство вывода (stdout).
Исходный текст основного приложения
#include <stdio.h>
#include <alf.h>
char* library_name = "alf_hello_world_hybrid_spu64.so";
char* spu_image_name = "alf_hello_world_spu";
char* kernel_name = "comp_kernel";
int main()
{
alf_handle_t handle;
alf_task_desc_handle_t task_desc_handle;
alf_task_handle_t task_handle;
alf_wb_handle_t wb_handle;
/* инициализация среды исполнения ALF */
alf_init(NULL, &handle);
alf_num_instances_set(handle, 1);
/* факультативно, по умолчанию ALF использует все доступные акселераторы */
/* creates the task descriptor */
alf_task_desc_create(handle, 0, &task_desc_handle);
alf_task_desc_set_int32(task_desc_handle, ALF_TASK_DESC_MAX_STACK_SIZE, 4096);
/* в ALF предусмотрен стек по умолчанию */
alf_task_desc_set_int64(task_desc_handle, ALF_TASK_DESC_ACCEL_IMAGE_REF_L,
(unsigned long long)spu_image_name);
alf_task_desc_set_int64(task_desc_handle, ALF_TASK_DESC_ACCEL_LIBRARY_REF_L,
(unsigned long long)library_name);
alf_task_desc_set_int64(task_desc_handle, ALF_TASK_DESC_ACCEL_KERNEL_REF_L,
(unsigned long long)kernel_name);
/* создание задания */
alf_task_create(task_desc_handle, NULL, 1, 0, 0, &task_handle);
/* создание рабочего блока и помещение его в очередь */
alf_wb_create(task_handle, ALF_WB_SINGLE, 1, &wb_handle); alf_wb_enqueue(wb_handle);
/* завершение задания */
alf_task_finalize(task_handle);
/* ожидание окончания выполнения задания */
alf_task_wait(task_handle, -1);
/* завершение работы среды исполнения ALF */
alf_exit(handle, ALF_EXIT_POLICY_FORCE, 0); /*
в большинстве случаев лучше использовать ALF_EXIT_POLICY_WAIT */
return 0;
}
|
 |
Исходный текст программы для акселератора
#include <stdio.h>
#include <alf_accel.h>
int comp_kernel(void *p_task_context, void *p_parm_context, void *p_input_buffer,
void *p_output_buffer, void *p_inout_buffer,
unsigned int current_count, unsigned int total_count)
{
printf("Hello World!\n");
return 0;
}
ALF_ACCEL_EXPORT_API_LIST_BEGIN ALF_ACCEL_EXPORT_API("comp_kernel", comp_kernel);
/* P93, "Здесь рекомендуется использовать идентификатор,
совпадающий с идентификатором соответствующей функции " */
ALF_ACCEL_EXPORT_API_LIST_END
|
|  |