Организация упреждающего кэширования в сетевой среде распределенных вычислений

ОРГАНИЗАЦИЯ УПРЕЖДАЮЩЕГО КЭШИРОВАНИЯ В СЕТЕВОЙ СРЕДЕ РАСПРЕДЕЛЕННЫХ ВЫЧИСЛЕНИЙ

И.Е. Сахаров

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

Введение

В работе представлена организация сервиса упреждающего кэширования в сетевой среде распределенных вычислений (ССРВ), которая позволяет использовать разнородные средства как единый вычислительный ресурс. При запуске задачи на выполнение могут возникнуть проблемы, связанные с тем, что исходные данные, необходимые для счета, располагаются в других компонентах ССРВ. Из большого территориального расположения компонент ССРВ возникает задержка передачи данных по каналам связи и задержка обращения к дисковым накопителям.

Основная проблема для получения выигрыша от ССРВ - сложность получения точных и своевременных предвыборок. Предлагается новый подход для генерации точных и своевременных предвыборок без участия программиста. Разница между временем вычисления одной процессорной операции и временем доступа к единице дисковой памяти постоянно увеличивается. Эта тенденция служит причиной того, что приложения должны осуществлять дополнительную выборку данных из дисковой памяти, до момента обращения к этим данным. Необходимость ускорения доступа к распределенным данным обуславливает актуальность задачи разработки упреждающего кэширования.

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

Архитектура упреждающего кэширования

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

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

Linux [1]. В большинстве случаев предполагается, что требуемые данные располагаются последовательно друг за другом. Для большинства обычных приложений этот подход является эффективным, но для приложений с интенсивным обменом данными подобный подход неэффективен. Как правило, подобные приложения обращаются одновременно к большому количеству файлов, распределенных произвольным образом между множеством ВС. В работе предлагается использовать механизм упреждающего кэширования, который учитывает реальную последовательность обращений к файлам. Команды предвыборки получают требуемую информацию в процессе дополнительного запуска кода оригинальной программы.

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

Предсказуемое упреждающее кэширование. Самые ранние разработки систем упреждающего кэширования основывались на методах, основанных на примерах и методах основанных на истории обращений [2].

Специальные приложения, контролирующие упреждающие выборки и кэширование. Подобными системами занимался Patterson [3]. Такой подход повысил эффективность исполнения приложения от 13 до 30%. Также в этом направлении работал Cao [4]. Он первым предложил интегрировать упреждающее кэширование с обычным кэшированием.

Специальное компилирование приложений. Основная идея этого направления заключается в исключении роли разработчика приложения для использования упреждающего кэширования. T. Mowry разработал компилятор, который осуществлял специальные вставки в код приложения [5]. Chang и Gibson [6] разработали средство SpecHint, которое специальным образом изменяло откомпилированные файлы, что позволяло использовать так называемое спекулятивное выполнение задачи в моменты блокирующих операций ввода/вывода.

Системная архитектура

Рис. 1. Системная архитектура

Упреждающее кэширование основывается на четырех компонентах: транслятор исходного кода, библиотека упреждающего кэширования, загрузочном модуле и модуле упреждающего кэширования.

Транслятор кода создает упреждающий поток из приложения путем выборки тех частей кода, которые относятся к вводу/выводу и урезанию всех вычислительных частей. Все вызовы ввода/вывода заменяются вызовами из библиотеки упреждающего кэширования. Само исходное приложение формирует вычислительный поток. Имеется однозначное соответствие между упреждающими вызовами в упреждающем потоке и вызовами ввода/вывода из оригинального приложения. Упреждающий поток выполняется как Linux поток, используя стандартную библиотеку phtread. Каждый упреждающий вызов обслуживается загрузочным модулем. Каждому упреждающему вызову ставиться в соответствие логический адрес требуемого блока данных. Множество упреждающих вызовов заноситься в пользовательскую очередь упреждающих вызовов. Когда пользовательская очередь упреждающих вызовов заполняется, модуль упреждающего кэширования осуществляет системный вызов, который передает эту очередь на выполнение модулю упреждающего кэширования. Естественно эти вызовы могут и не выполниться, если например, не будет ресурсов для выполнения их, тогда модуль запустит их через некоторую паузу.

Основная сложность заключается в реализации синхронизации вычислительного и упреждающего потока. Синхронизация позволяет избежать отставания упреждающего потока от вычислительного потока. Необходимо осуществлять постоянную проверку файлов на предвыборку. Нужно точно знать, что подкачиваемые файлы будут использоваться в ближайшее время, а не использовались уже. Если условие не выполняется, то получается дополнительная работа и сильное уменьшение производительности выполнения реального приложения. Основная идея синхронизации строится на метках. Каждому упреждающему запросу ставится некоторый идентификационный номер ID соответствующего упреждающего вызова, исполняющего этот запрос. Модуль упреждающего кэширования также содержит номер ID текущей операции ввода/вывода вычислительного потока. Если номер записи в упреждающей очереди меньше, чем номер самого последнего вызова, то получается, что вычислительный поток обгоняет упреждающий, и тогда модулю упреждающего кэширования указывается пропустить все команды, поставленные для выполнения. Чтобы не получилось ситуации, когда упреждающий поток слишком опережает вычислительный поток, предусматривается некоторое расстояние N, на которое вычислительный поток может отставать от упреждающего потока. Это расстояние, например, можно привязать к среднему времени выполнения диском операции ввода/вывода, которую можно измерить заранее или просто к некоторому фиксированному числу.

Упреждающий поток

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

Программный интерфейс упреждающего потока включает в себя четыре функции библиотеки:

(1) create_prefetch_thread(prefetch_function): эта функция позволяет приложению создать упреждающий поток и выполнить prefetch_fuction. Prefetch_function является входным параметром;

(2) prefetch_xxx(): это множество функций, которые заменяют в упреждающем потоке все стандартные функции ввода/вывода. Эти функции имеют такой же синтак-

сис, как и обычные функции ввода/вывода. Например, функция read(stream, ptr, size) заменяется функцией prefetch_read(stream, size);

(3) inform_open(file_pointer) и inform_close(file_pointer): эти функции необходимы, чтобы информировать упреждающий поток об открытии или закрытии файлов вычислительным потоком. Эти функции является необходимыми, поскольку модуль упреждающего кэширования составляет таблицу, содержащую две записи {file pointer, current offset} для всех файлов, использующихся в упреждающем потоке;

(4) synchronize(synchronization_point, type): эта функция синхронизации двух потоков. Аргумент type может принимать два значения: signal или wait.

int fp;

Вычислительный поток Упреждающий поток

void main(void){ Void prefetch_fuction(void){

int i; int data[100]; int I;

/*создание упреждающего потока*/

create_prefetch_thread(

(void*)prefetch_function);

##C1 /*открытие файла данных*/

fp=open("mydata.dat", O_RDONLY);

/*сигнал упреждающему потоку*/

C2 synchronized, signal); /*ожидание открытия файла*/

synchronize(1, wait);

##C3 /*указание об открытии файла*/

$$P1 inform_open(fp);

for(i=99; i>=0; i--){ /*предвыборка*/

/*ввод-вывод*/ $$P2 for(i=99; i>=0; i--){

C4 lseek(fp, i*4, SEEK SET);

read(fp, &data[99-i], 4); P3 /*только ввод-вывод*/

C5 /*вычисления*/ prefetch_lseek(fp,i*4,SEEK_SET);

C6 data[99-i] = data[99-i]*i; prefetch_read(fp, 4);

} P4

C7 /*закрытие файла*/ P5

close(fp); }

} /*указание о закрытие файла*/

C8 inform_close(fp);

$$P6 } }

Рис. 2. Слева - вычислительный поток, справа - упреждающий поток. Внутри функции main строчки без ## являются оригинальным кодом приложения. В этот код были вставлены изменения по созданию упреждающего потока. Строчки без символа $$ были взяты с оригинального кода приложения. В упреждающем потоке

не присутствуют вычисления

Синхронизация

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

(1) Открытие файла. Упреждающий поток должен ожидать, пока вычислительный поток откроет файл. Потоки синхронизируются вызовом synchronize() с указанием номера синхронизационной точки. Вычислительный поток открывает файл и вызывает функцию synchronize для указания, что файл был открыт. Упреждающий поток вызывает функцию synchronize и ожидает получение сигнала от вычислительного потока. Линии С3 и Р1 на рис.2 представляют собой точки синхронизации для двух потоков. Функция синхронизации использует функции pthread_cond_wait и pthread_cond_signal

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

(2) Ввод информации пользователем. Упреждающий поток вынужден ожидать, пока вычислительный поток вычислит адрес на основе входной информации(stdin) или считает его из специального файла. Если адрес следующих данных зависит от данных файла, для которого уже осуществляется предвыборка, тогда в каждый из потоков вставляются точки синхронизации. В этом случае упреждающий поток продолжит выполнение только после того, как вычислительный поток считает требуемую информацию из буфера кэш-памяти. Если входные данные считываются из конфигурационных файлов, тогда также добавляются точки синхронизации.

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

Обмен данными между потоками

Оба потока могут обмениваться данными через глобальные переменные, используемые в приложении. Также необходимо, чтобы потоки могли самостоятельно обмениваться информацией. Для этого между потоками создается коммуникационный канал или просто канал pipe.

Вычислительный поток

void main(void){ Void prefetch_fuction(void){

int fp; int data, int index; int fp, int index;

/* FILE *config_fp */ FILE *config_fp;

XX create_prefetch_thread(

##C1 (void*)prefetch_function);

fp=open("mydata.dat", O_RDONLY);

C2 /*посылка дескпритора для УП*/ /*получение дескриптора*/

send_fileptr(fp); receive_fileptr(&fp);

##C3 $$P1 inform_open(fp);

/*config_fp=fopen("config.dat","r");*/ $$P2 config_fp = fopen("config.dat", "r");

XXC4 P3 /*ввод-вывод*/

/*flseek(config_fp,10,SEEK_SET);*/ flseek(config_fp,10,SEEK_SET);

XXC5 P4

/*чтение и посылка ВП*/

/*fscanf(config_fp, "%d", &index);*/ send_fscanf(config_fp,"%d", &index);

XXC6 /*ожидание данных от УП*/ P5

receive fscanf("%d", &index);

##C7 lseek(fp, index*4, SEEK_SET); prefetch lseek(fp,index*4,

C8 P6 SEEK_SET);

read(fp, &data, 4); P7 prefetch_read(fp, 4);

C9 data = data + 10;

C10

close(fp); $$P8 inform close(fp);

C11 } }

Рис. 3. Обмен данными между потоками. Локальные переменные fp и index должны быть доступны обоим потокам. Строки, помеченные XX, были изъяты из вычислительного потока и помещены в упреждающий поток. Строки, не помеченные $$, были взяты из оригинального кода приложения

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

(1) send_fileptp(file_pointer), receive_fileptr(file_pointer): эти две функции осуществляют пересылки файловых указателей между потоками. В эти функции включена синхронизация и не нуждаются в запуске дополнительной синхронизации (линии С3 и Р1 на рис. 3).

(2) send_xxx() и receive_xxx(): это множество функций использующихся для передачи информации между потоками. Например, для функции fscanf(fp, "%d", &value) предусмотрены две функции send_fscanf(fp, "%d", &value) и receive_fscanf("%d", &value). Функция посылки send_fscanf считывает значение и посылает его в канал. Переменная fp для функции receive_fscanf не нужна, поскольку она считывается из канала. Для распознавания файлов конфигурации предлагается проверять имена файлов на наличие фраз conf, configure и config. На рис. 3 это показано крестиками. Вместо scanf в упреждающий поток вставляется функция send_fscanf, а в вычислительный поток вставляется функция receive_fscanf.

Внутренний анализ зависимостей функции

Цель анализа заключается в построении зависимостей внутри функции. В результате анализа определяются все переменные и выражения, относящиеся к дисковому вводу/выводу. Пусть P(x) - это некоторое множество выражений включающих в себя прямо или косвенно переменную x внутри конкретной функции. Используется достаточно простой подход.

(1) Все выражения, которые изменяют переменную х, включая определение этой переменной, включаются в множество P(x).

(2) Вычислим некоторое множество А, содержащее все переменные, используемые в выражениях из множества P(x).

(3) Для каждой a G А включим Р(а) в Р(х).

Для блочной структуры языка Си при выполнении шага 1 (построение множества Р(х)) необходимо ограничиваться областью, где определена переменная х для функции. Например, рассмотрим фрагмент кода. Здесь 4 и 5 строки не должны включаться в множество P(x).

1. void main(void){

2. int i;

3. i= 5;

4. { int i;

5. i= 6;

6. }

7. lseek(fp, i, SEEK_SET);

8. }

Представленный алгоритм является простым и очень быстрым, но у него есть ряд недостатков. Алгоритм может включать много лишних выражений, которые никогда не заканчиваются операциями ввода/вывода или не влияют на операции ввода/вывода. Существующие компиляторы способны осуществлять проверку и убирать лишние части кода, которые не влияют на функционирования программы. Любой компилятор обладает мощным анализатором кода, который может найти и убрать неиспользуемые фрагменты. Поэтому предположим, что компилятор уберет лишнее. Тогда наш простой алгоритм становится достаточно эффективным.

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

1. Все операции ввода/вывода в коде программы, которые относятся к файлам, к которым применимо упреждение, должны быть включены во множество операций, влияющих на ввод/вывод. Для каждой переменной x, встречающейся в выражениях дискового доступа к данным, строится множество P(x), и результат включается в УП.

2. Если в цикловой структуре, т.е. for, while, do-while, if-then-else или case, встречаются выражения, относящиеся к УП, то все используемые внутри переменные помечаются как влияющие на дисковые операции (помечаются с помощью массива булевых переменных). Для каждой такой переменной a строится множество P(a) и включается в УП. Эту операцию необходимо выполнить до конца.

3. Вставить в УП определения всех выражения и переменных, помеченных как влияющие на дисковые операции ввода/вывода.

4. Вставить в УП вызовы синхронизации(synchronize), посылки(send_xxx) и приема(receive_xxx) для передачи данных между потоками.

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

Этот алгоритм запускается итеративно для каждой процедуры до тех пор, пока не дойдет до конца приложения.

Внешний анализ зависимостей функций

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

1. Для каждой функции T пусть Q(x1, x2 , ..., xn) - это одна из процедур, которые вызывает T с параметрами (y1, y2, ..., yn). Если любой из параметров yi является зависимым для дискового ввода/вывода в функции Т(т.е. значение переменной может быть изменено в функции Q), то это указывает, что переменная xi внутри процедуры Q, также влияет на дисковый ввод/вывод. Если функция T сохраняет возвращаемое значение функцией Q в некоторую переменную a, то а также влияет на дисковый ввод/вывод в функции T.

2. Для каждой процедуры T(y1, y2, ..., yn) пусть R - это функция, которая вызывает Т c параметрами T(z1, z2, ..., zn). Если параметр yi влияет на дисковый ввод/вывод в функции T, то это означает, что параметр zi также влияет на дисковый ввод/вывод в R.

3. Все глобальные переменные, влияющие на ввод/вывод во всех функциях, также влияют на ввод/вывод.

Выше представленный алгоритм применяется для каждой функции лишь один раз, если нет рекурсивного вызова. Если такие вызовы есть, то алгоритм применяется до тех пор, пока не закончится выполнение.

Ограничения

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

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

Архитектура исполняющей системы

Библиотека упреждающих вызовов

Все вызовы упреждения, которые использует упреждающий поток, содержатся в библиотеке упреждающих вызовов. На самом деле это загрузочный модуль для работы упреждающего кэширования, который использует библиотеку упреждающего кэширования, а также размещает и хранит в памяти очередь команд на упреждение и адреса блоков, которые должны быть упреждены. Структура очереди команд на упреждение имеет следующий вид: {идентификатор файла, номер блока, идентификатор вызова}. Идентификатор файла и блока определяют реальный физический блок данных, который необходимо предвыбрать. Идентификатор вызова определяет вызов, который инициировал запуск механизма упреждения для данного блока. Начальное значение идентификаторов вызовов начинается с 0. Файловая таблица для каждого файла дескриптора содержит смещение. Используя эту информацию, всегда можно вычислить номер блока для вызовов prefetch read и prefetch lseek.

Упреждающий поток

prefetch freadO

Загрузочный модуль Библиотека упреждающего кэширования

ID вызова упреждения

Файловая таблица

Очередь упреждающих вызовов

Файловый указатель Смещение

Вычислительный поток

fread

Модуль

упреждающего кэширования

Системный вызов

Дисковая очередь

Очередь упреждающих вызовов

Текущий ID вызова

Сравнение] Предвыборка

Рис. 4. Архитектура исполняющей системы

Каждому вызову ставится в соответствие идентификатор этого вызова. Потом счетчик идентификаторов вызовов увеличивается на 1 (рис. 4). Далее ГО вызова помещается в очередь на предвыборку. В конце происходит обновление текущего смещения в файле. Как только очередь упреждающих вызовов заполняется, она перемещается в очередь модуля упреждающего кэширования на исполнение. Когда приложение выполняет функцию create_prefetch_thread(), то загрузочный модуль, используя вызов йгЦ) запускает поток упреждения и передает модулю упреждающего кэширования идентификаторы вычислительного и упреждающего потоков. Загрузочный модуль так-

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

Модуль упреждающего кэширования

Основная задача модуля состоит в запуске процессов копирования и постоянной проверке: упреждающий поток должен быть всегда впереди вычислительного на определенное количество команд. Когда загрузочный модуль определяет, что очередь запросов на упреждение заполнилась, то она передается модулю упреждающего кэширования на исполнение. Если очередь модуля упреждающего кэширования заполнена, то загрузочный модуль делает паузу в передаче своей очереди. Как только модуль упреждающего кэширования освободит свою очередь, он передает сигнал загрузочному модулю, и тот передает остановленные ранее вызовы. Передача осуществляется, когда очередь в загрузочном модуле полностью заполнится. Размер очереди модуля упреждающего кэширования больше, чем размер очереди загрузочного модуля.

Получается следующая модель исполнения приложения: в момент, когда вычислительный поток производит обращение к некоторым данным, эти данные уже находятся в файловом буфере, так как к ним уже было осуществлено обращение при исполнении упреждающего потока. Таким образом, уменьшается количество блокирующих операций ввода/вывода, и тем самым увеличивается эффективность выполнения приложения. Подобная схема эффективно работает для приложений с периодическими постоянными вызовами доступа к данным. Для упреждающего потока выставляет более высокий приоритет по сравнению с вычислительным потоком. Перед тем, как исполнить любой запрос из очереди модуля упреждающего кэширования, происходит сравнение идентификаторов вызовов упреждающего и вычислительного потока. Если идентификатор упреждающего потока меньше, чем идентификатор вычислительного, то модуль просто удаляет этот вызов из очереди и переходит к выполнению следующего.

Пусть К - текущий размер очереди модуля упреждающего кэширования, Т -среднее время исполнения одного запроса из очереди, а среднее время вычислений между двумя дисковыми вызовами пусть будет С. Предположим, что 1 - текущее время, текущий идентификатор вызова вычислительного потока будет 1, а упреждающего потока будет _]. Тогда время, до момента, когда приложение обратится к некоторому блоку, будет равняться С*( - 1). Упреждающий вызов, который посылается в дисковую очередь на выполнение во время 1, будет исполнен ко времени 1+(К+1)*Т. Модуль упреждающего кэширования должен выполнить операцию упреждения, только если выполняются следующие условия:

(1) (С*( - 1)) - ((К+1)*Т) < временного предельного значения;

(2) ( - 1) < предельного ограничения дисковой очереди.

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

Тестирование

Использовались следующие тестовые приложения.

(1) Подсчет некоторой характеристики для двух матриц размером 512*512x512, где каждый элемент равняется байту. Общий размер каждой матрицы составлял 130 Гбайт. Каждая матрица была поделена на 4 файла по 33 Гбайт и размещена на двух диска по 2 файла на каждом. Исполнялась задача расчета характеристики.

(2) Получение новой матрицы из имеющихся по следующему принципу: пусть А и В - исходные матрицы, А(х,у,2) и Б(х,у,2) - элементы исходных матриц, тогда элемент новой матрицы С рассчитывается следующим образом:

Qx,y,z) = B(x,y,z)xA(511-x,511-y,511-z) xB(x+a,y+a,z+a)/ A(x+b,y+b,z+b).

Размер блока был равен 4 Кб. По результатам тестирования были получены следующие результаты. Для первого случая уменьшение времени выполнения приложения с применением упреждающего кэширования составило порядка 41,23%, для второго случая - порядка 23,99%.

Заключение

В статье представлена организация упреждающего кэширования на основе метода разделения потоков. Для доказательства эффективности введения упреждающего кэширования была разработана имитационная модель упреждающего кэширования для ССРВ в пакете GPSS[7]. Разработанный метод упреждающего кэширования, основанный на методе разделения потоков, позволяет решить задачу определения последовательности будущих обращений к файлам для большого множества различный приложений с интенсивным обменом данными. Основная идея заключается в разложении приложения на два потока: вычислительный поток, содержащий неизмененный код оригинальной программы, включающий все вычислительные операции и все операции ввода/вывода, и упреждающий поток, содержащий все оригинальные инструкции, которые имеют отношение к вводу/выводу.

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

Литература

1. M.K. McKusick. A Fast File System for UNIX // ACM Transaction on Computer System, 2(3), August 1984.

2. K. Curewitz. Practical Prefetching via Data Compressing // ACM Conference on Management of Data, May 1993.

3. R. Hugo Patterson, Garth A. Gibson, M. Satyanarayanan. A Status Report on Research in Transparent Informed Prefetching // ACM Operating Systems Review, 1993.

4. Kieran Harty, David R. Cheriton. Application-controlled physical memory using external page-cache management / Proceedings of the fifth international conference on Architectural support for programming languages and operating systems, 1992.

5. Todd C. Mowry, Angela K. Demke, Orran Krieger. Automatic Compiler-Inserted I/O Prefetching for Out-of-Core Applications / Proceedings of the 1996 Symposium on Operating Systems Design and Implementation.

6. Fay Chang, Garth A. Gibson. Automatic I/O Hint Generation through Speculative Execution / Operating Systems Design and Implementation, 2001.

7. Киселев А., Корнеев В., Семенов Д., Сахаров И. Управление метакомпьютерными системами // Открытые системы. - 2005. - №2.