\documentclass[%showframe%
]{oclh_doc}
\usepackage{fix-cm}%   fix of Computer Modern font DO NOT MOVE!!!
\usepackage{calc}%     simple arithmetic in expressions
\usepackage{etoolbox}% some Latex interfaces
\usepackage{longtable,multirow}% tables
\usepackage{adjustbox,%
            placeins, % processing of float objects
            caption}  %
%
% page geometry
%
\usepackage[
    top    = 0.06734007\paperheight,
    bottom = 0.06734007\paperheight,
    right  = 0.1190476\paperwidth,
    left   = 0.0952381\paperwidth
]{geometry}
%
% language and fonts
%
\usepackage{amsmath,amsfonts,amssymb,xfrac}
\usepackage[cmintegrals,cmbraces]{newtxmath}
\usepackage{xltxtra,polyglossia,csquotes}
\usepackage{verbatim,fancyvrb,framed}
\usepackage{relsize}
\setmainlanguage{russian}
\setotherlanguage{english}
\setkeys{russian}{babelshorthands=true}
\defaultfontfeatures{Scale=MatchLowercase,Mapping=tex-text}
\input{fonts/font_settings-IBM_Plex.tex}
% \input{fonts/font_settings-Computer_Modern.tex}
% \input{fonts/font_settings-my_fonts.tex}

%
% paragraphs and align
%
\usepackage{indentfirst}
\frenchspacing\sloppy\raggedbottom
\setlength{\parindent}{0.0604762\paperwidth}%
%%%%% additional colontitles settings
\RequirePackage{fancyhdr}
\fancyhf{}\renewcommand{\headrulewidth}{0pt}
\fancyfoot{}
\fancyfoot[R]{\thepage}
\pagestyle{fancy}
%
% index
%
\usepackage[xindy]{imakeidx}
\makeindex[options = -C utf8 -M texindy -M index_style_and_order ]
%
% references
%
\RequirePackage{hyperref}
\RequirePackage{xcolor}
\definecolor{DarkBlue}{rgb}{0,0,0.5}
\hypersetup{colorlinks=true,       linkcolor={black},
            urlcolor  =DarkBlue, citecolor={black}}
%
% lists
%
\usepackage{enumitem}

\newenvironment{CodePar}%
    {\Verbatim[samepage=true,frame=single]}%
    {\endVerbatim}%
%
\newenvironment{CodeParWithCC}[1]
    {\Verbatim[samepage=true,frame=single,commandchars=#1]}
    {\endVerbatim}
%
\newenvironment{ImpNote}
    {\setlength{\parindent}{0.0604762\paperwidth}%
     \setlength{\LTleft}{\parindent}%
     \setlength{\LTpre}{\parsep}\setlength{\LTpost}{\parsep}%
     \begin{longtable}{|p{\linewidth-\tabcolsep-1\parindent}}
     \noindent\textsf{Важное замечание:}}
    {\end{longtable}}
%
\newcommand{\SetLenVarWithWidth}[2]{%
 \ifdefined #1 \else%
  \newlength{#1}%
 \fi%
 \settowidth{#1}{#2}%
}%
\newcommand{\NmCnvDescript}%
    {\addtolength{\leftskip}{0.0604762\paperwidth}%
     \setlength{\parindent}{-0.0604762\paperwidth}}%
%

\newcommand{\verbI}[1]{\textit{\Verb|#1|}}%
\newcommand{\verbIU}[1]{\underline{\smash{\textit{\Verb|#1|}}}}

\title{Библиотека OpenCL\_helpers}
\author{hk@r4in.tk\\ mns@r4in.tk}
\makeindex
\begin{document}
\maketitle

\section{Вводная информация}

Библиотека OpenCL\_helpers создана для облегчения программирования
многопоточных приложений, использующих GPGPU (General-purpose computing on
graphics processing units -- вычисления общего назначения на графических
процессорах). Библиотека не перекрывает всех потребностей программирования
приложений, использующих GPGPU, она написана для упрощения создания приложений
использующих многоуровневый (иерархический) параллелизм на одном компьютере. То
есть, она позволяет распараллеливать задачу на потоки (threads) на основном
вычислительном устройстве (CPU), а затем задачу каждого треда распараллеливать
на устройстве GPGPU, разбивая GPU-потоки на команды выполняющие разные задачи.

При создании библиотеки предполагалось, что каждый CPU-поток использует
отдельное устройство GPGPU, однако не запрещено использовать одно устройство
GPGPU в двух и более CPU-потоках. Параллелизм на уровне CPU обеспечивается
средствами POSIX Threads, параллелизм на уровне GPGPU обеспечивается средствами
библиотеки.

Библиотека состоит из четырёх частей, не все из которых прямо связаны с
параллелизмом и которые могут использоваться независимо друг от друга.

Первая часть это средства сборки программ OpenCL~(п.\ref{sec:buildutils}).
Средства сборки позволяют собирать программы OpenCL из командной строки и
просматривать результат без написания и запуска собственного приложения.

Вторая часть~(п.\ref{sec:libraryusing}) это сами CPU-функции OpenCL\_helpers и
синтаксис, позволяющий создавать заголовочные файлы~(headers) общие для CPU и
GPGPU программ.

Третья часть~(п.\ref{sec:memalloc}) восполняет недостаток средств управления
памятью в OpenCL C вводя средства выделения и освобождения памяти GPGPU,
диагностики кучи~(heap) и реинтерпретации~(cast) указателей~(pointers).

Четвёртая часть~(п.\ref{sec:squadmodel}) -- GPGPU-функции, позволяющие
организовывать параллелизм внутри GPGPU, разбивая все множество GPGPU-потоков на
команды, занимающиеся выполнением отдельных задач.

\subsection{Сборка и установка}
\label{sec:build_n_install}

\subsubsection{Требования}
\label{subsec:prerequisites}

Предполагается, что вы имеете:

\begin{enumerate}[leftmargin=2\parindent]
 \item Компьютер с установленной ОС Linux.
 \item Установленный и работающий компилятор языка C.
 \item Установленную и доступную стандартную библиотеку языка C (libc).
 \item Установленное программное обеспечение OpenCL версии 1.2 или младше любого
 производителя.
\end{enumerate}

\subsubsection{Получение исходного кода библиотеки OpenCL\_helpers}
\label{subsec:getting_source}

Получить копию исходного кода библиотеки OpenCL\_helpers можно по адресу
\href{https://ggs.void.r4in.tk/hk/OpenCL_helpers/archive/master.tar.gz}%
{\Verb|https://ggs.void.r4in.tk/hk/OpenCL\_helpers/archive/master.tar.gz|}
после чего распаковать полученный архив.

Кроме того, при наличии установленной СКВ Git~(\href{https://git-scm.com}%
{\Verb|https://git-scm.com|}) можно получить исходный код
библиотеки OpenCL\_helpers командой\par
\indent\indent\verb|git clone |%
\href{https://ggs.void.r4in.tk/hk/OpenCL_helpers.git}%
{\Verb|https://ggs.void.r4in.tk/hk/OpenCL\_helpers.git|}


\subsubsection{Сборка}

Для сборки по умолчанию необходимо перейти в каталог \verb|OpenCL_helpers| и
выполнить команду

\indent\indent\verb|make|

\noindent%
Допустимо использовать ключ \verb|-j| для многопоточной сборки. Если команда
завершена без ошибок, то в каталоге \verb|OpenCL_helpers/build| появятся файлы:
\par
\indent\indent\verb|liboclh.so.|\verbI{I}\verb|.|\verbI{J}%
\verb|    oclh_br    oclh_cr    oclh_lr|\par
\noindent%
и несколько подкаталогов \verb|*.o| с объектами. В имени первого файла
\verbI{I} -- майорная версия библиотеки, а \verbI{J} -- минорная. Каждый файл
может быть собран отдельно командами:\par
\indent\indent\verb|make oclh_library|\par
\indent\indent\verb|make oclh_builder|\par
\indent\indent\verb|make oclh_compiler|\par
\indent\indent\verb|make oclh_linker|\par
При необходимости возможна сборка для отладки (debug) командой\par
\indent\indent\verb|make debug|

\subsubsection{Установка}

Установка осуществляется командой:\par
\indent\indent\verb|make install|\par
\noindent%
В результате будет создан каталог \verb|~/opt/oclh|, куда в подкаталоги
\verb|bin|, \verb|lib|, \verb|include| будут скопированы исполняемые файлы, файл
библиотеки и заголовочные файлы соответственно. Затем целесообразно добавить
каталог \verb|~/opt/oclh/bin| в переменную окружения \verb|PATH|, а каталог
\verb|~/opt/oclh/lib| -- в переменную окружения \verb|LD_LIBRARY_PATH|.

Можно изменить целевой путь если задать команду

\indent\indent\verb|make PRFX_PATH=|\verbI{путь\_установки}\verb| install|

\subsubsection{Удаление}

Удаление производится командой

\indent\indent\verb|make uninstall|

\noindent%
либо

\indent\indent\verb|make PRFX_PATH=|\verbI{путь\_установки}\verb| uninstall|

\noindent%
если установка производилась не в каталог по умолчанию.

\subsubsection{Документация}

Документация библиотеки OpenCL\_helpers собирается отдельно. Для её сборки
необходима система вёрстки \XeTeX /\XeLaTeX\ или иная \TeX /\LaTeX-система.
Система \XeTeX\ и сопутствующие пакеты поставляются в составе дистрибутива \TeX
~Live~(\href{https://www.tug.org/texlive/}%
{\Verb|https://www.tug.org/texlive/|}). Использование системы отличной от
\XeTeX\ может потребовать внесения изменений в исходный код документации.

Кроме непосредственно системы вёрстки понадобится ещё ряд пакетов, например,
xindy для составления предметного указателя. Все использованные при составлении
документации пакеты свободно доступны в составе дистрибутива \TeX ~Live.

Сама сборка документации осуществляется из каталога
\verb|OpenCL_helpers/documentation| запуском сценария сборки\par
\indent\indent\verb|./build_script|\par
\noindent%
Если в ходе исполнения данного скрипта не возникло ошибок, то в каталоге
\verb|OpenCL_helpers/documentation/build| появятся файлы\par
\indent\indent\verb|opencl_helpers_documentation-russian.pdf|\par
\indent\indent\verb|opencl_helpers_documentation-english.pdf|\par
\noindent%
с документацией на русском и английском языках соответственно.

При сборке будут использованы шрифты семейства IBM~Plex, но можно вернуться к
базовому семейству Computer~Modern просто раскомментировав строку\par
\indent\indent\verb|\input{fonts/font_settings-Computer_Modern.tex}|\par
\noindent в преамбуле исходного кода документации.

\subsection{Формат файла-журнала}
\label{subsec:logformat}

\index{формат файла-журнала}%
Средствами библиотеки можно вести файлы-журналы~(logs) о происходящих в
приложении событиях, кроме того сама библиотека при необходимости будет
осуществлять записи в файл(ы)-журналы. Описание функций журналирования
дано~в~п.\ref{subsec:logfunctions}.

Стандартная запись в файле журнале выглядит как

\begin{CodeParWithCC}{\\\{\}}
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} \textit{содержание_сообщения}
\end{CodeParWithCC}

\noindent где\par
{%
\setlength{\leftskip}{0pt}%
\setlength{\LTpre}{\smallskipamount}\setlength{\LTpost}{\smallskipamount}%
\setlength{\LTleft}{2\parindent-\tabcolsep}
\SetLenVarWithWidth{\Acol}{\verbI{YYYY}}%
\SetLenVarWithWidth{\Bcol}{--}%
\begin{longtable}%
    {p{\Acol}p{\Bcol}p{\linewidth-\LTleft-\Acol-\Bcol-5\tabcolsep}}
\verbI{YYYY}&--&год, записанный четырьмя десятичными цифрами;\\
\verbI{MM}&--&месяц года, записанный двумя десятичными цифрами от 01 до 12;\\
\verbI{DD}&--&день месяца, записанный двумя десятичными цифрами от 01 до 31;\\
\verbI{hh}&--&час дня, записанный двумя десятичными цифрами от 00 до 23;\\
\verbI{mm}&--&минута часа, записанная двумя десятичными цифрами от 00 до 59;\\
\verbI{ss}&--&секунда минуты, записанная двумя десятичными цифрами от 00 до 59;
\\
\verbI{HHHH}&--&последние два байта адреса рабочей конфигурации устройства
GPGPU~(workset,~подробнее~см.~п.\ref{subsec:structures}), записанные четырьмя
шестнадцатеричными цифрами.
\end{longtable}
}\par
\noindent%
\verbI{содержание\_сообщения}~--~может быть любым текстом переданным функции
журналирования, однако в коде самой библиотеки соблюдаются по возможности
следующие соглашения:
\begin{enumerate}
  \item Информация об объектах (сущностях) OpenCL записывается как
  \verbI{тип\_объекта}\verb|_0x|\verbI{HHHH}, где \verbI{HHHH}~--~последние два
  байта адреса объекта, записанные четырьмя шестнадцатиричными цифрами. Так,
  например, устройство GPGPU может быть записано как \verb|dev_0x2a78|, а
  платформа как \verb|platform_0xf190|. Исчерпывающий список сущностей OpenCL
  дан в спецификациях OpenCL.
  \item В качестве разделителей блоков информации в сообщении и маркирования
  относительности блоков используется символ <<\verb+|+>>. Так
  запись\nopagebreak
  \begin{CodePar}
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  dev_0xf260 | ...
  \end{CodePar}
  обозначает, что сообщение относится к OpenCL-контексту \verb|0x9f60|,
  использующему устройство GPGPU \verb|0xf260|.
  \item В случае вывода в журнал информации, являющейся уточнением, перед ней
  ставится дополнительный пробел, например:\nopagebreak
  {\scriptsize
  \begin{CodePar}
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 | Reference count: 1
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 | Number of devices: 1
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 | Device ID(s): 0x1acf260
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  dev_0xf260 | GPU: 15 units/17...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  dev_0xf260 | Memory: 8116.43...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  dev_0xf260 | Vendor: NVIDIA Corp...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  dev_0xf260 | Model: GeForce GT...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 | Context properties:
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  Platform: 0xf190
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |   platform_0xf190 | Profile: FULL_PROFILE
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |   platform_0xf190 | Version: OpenCL 1...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |   platform_0xf190 | Name: NVIDIA CUDA
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |   platform_0xf190 | Vendor: NVIDIA Corp...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |   platform_0xf190 | Extensions: cl_khr...
2019-06-03 15:42:47 ws_0x9c00 context_0x9f60 |  Is user responsible for sync: Undefined (presumable No)
  \end{CodePar}
  }
  \item В случае возникновения ошибки при выполнении функции библиотеки в
  журнал будет добавлена запись, начинающаяся с \verb|oclerr:| и содержащая
  информацию о всех вызовах функций начиная с библиотечного и до OpenCL API. Так
  сообщение в журнале:\nopagebreak
  \begin{CodeParWithCC}{\\\{\}}
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} oclerr:
_ghf_getBuildStatus/clGetProgramBuildInfo/CL_PROGRAM_BUILD_STATUS
returned error -3 - CL_COMPILER_NOT_AVAILABLE
  \end{CodeParWithCC}
  значит, что функция \verb|_ghf_getBuildStatus| вызвала функцию OpenCL API
  \verb|clGetProgramBuildInfo| с аргументом \verb|CL_PROGRAM_BUILD_STATUS| и
  получила в ответ ошибку с кодом \verb|-3|, которая обозначает
  \verb|CL_COMPILER_NOT_AVAILABLE|.
\end{enumerate}

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

Кроме стандартной записи файла журнала существует ещё запись-заголовок, которая
выглядит как\par
{\small%
\begin{CodeParWithCC}{\\\{\}}
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} _______________
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} \textit{Текст_заголовка}
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} ~~~~~~~~~~~~~~~
\end{CodeParWithCC}
}\par
\noindent и запись-разделитель\par
{\small%
\begin{CodeParWithCC}{\\\{\}}
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} ____________________________________________________
\textit{YYYY}-\textit{MM}-\textit{DD} \textit{hh}:\textit{mm}:\textit{ss} ws_0x\textit{HHHH} ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
\end{CodeParWithCC}
}

\input{name_conventions-russian.tex}

\section{Средства сборки программ OpenCL}
\label{sec:buildutils}

В состав библиотеки входят три исполняемых файла:\nopagebreak\par
\begin{itemize}[leftmargin=1.75\parindent]
  \item\verb|oclh_cr| -- осуществляет компиляцию программы OpenCL в объект
  OpenCL;
  \item\verb|oclh_lr| -- осуществляет компоновку объектов OpenCL;
  \item\verb|oclh_br| -- осуществляет полную сборку программы OpenCL.
\end{itemize}\nopagebreak\par
Во время работы этих программ ведётся подробный диагностический журнал в файле
\verb|oclh_*r.log| (соответственно названию программы), куда сохраняется
избыточная информация обо всех доступных устройствах GPGPU, используемых
платформах и созданных для сборки контекстах. Фактически вы можете запустить,
например, \verb|oclh_сr| с любым входным файлом, даже с самим собой, как
\verb|./oclh_сr oclh_сr|. Файл, конечно, не будет собран в объект OpenCL, но в
журнале \verb|oclh_сr.log| останется полная информация по устройствам GPGPU,
найденным в системе. Формат журнала человекочитаем, адаптирован к поиску
подстрок с использованием команды \verb|grep| и аналогов. Формат файла-журнала
описан в п.\ref{subsec:logformat}.

Рассмотрим варианты использования каждой из этих программ.


\input{tools_compiler-russian.tex}
\input{tools_linker-russian.tex}
\input{tools_builder-russian.tex}

\section{Использование библиотеки OpenCL\_helpers. Структуры, функции и
заголовки}
\label{sec:libraryusing}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\subsection{Структуры}
\label{subsec:structures}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\subsubsection{Основная структура рабочей конфигурации}
\label{subsec:workset}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\subsection{Функции журналирования}
\label{subsec:logfunctions}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\subsection{Общие для CPU и GPGPU кода заголовочные файлы}
\label{subsec:sharedheaders}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\section{Управление памятью и реинтерпретация указателей в программах OpenCL C}
\label{sec:memalloc}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\section{Параллелизм внутри GPU}
\label{sec:squadmodel}

Заглушка. Раздел будет оформлен после достаточного тестирования
функциональности.

\let\originalstyle=\thispagestyle
\def\thispagestyle#1{}
\printindex
\let\thispagestyle=\originalstyle

\tableofcontents

\end{document}
