Mantius писал(а):Не дадите ссылочку где почитать подробнее?
Ни одна ссылка на ум не приходит.
Да и нет ничего мудрёного в этой идее:
У вас откуда-то берутся данные, либо из файла, либо снимаются с каких-то датчиков. Вы эти данные представляете себе мыслено в виде последовательности/потока значений. Например, в вашем случае на входе матрица M*N, её можно представить виде последовательности M рядов в каждом из которых N значений, всё вместе - поток значений размером M*N.
Например, эта матрица записана в файле, вначале файла, два целых числа M (число строк, до 1000) и N (число столбцов, до 1000), далее следуют M*N значений (real) ячеек. Нужно усреднить значения в матрице: получит матрицу K*L, где K = M/2, L = N/2, а каждое значение - среднее арифметическое остальных соседних 4 клеток исходной матрицы.
Входная матрица занимает 1000 * 1000 * 6 = 6 000 000 ~ 6Гб.
Выходная матрица занимает 500 * 500 * 6 = 1 500 000 ~ 1,5Гб
Входная матрица в памяти не умещатся, выходная если и вместиться, то в притык (т.к. на пользовательское простанство на 32-биных системах выделяется ~ 2Гб, в котором кроме ваших данных ещё располагается ваш код и код используемых библиотек, в том числе системных).
Но одна строка выходной матрицы занимает 500 * 6 = 3000 ~ 3Кб, т.е. мы можем смело держать в памяти одну выходную строку. А значит мы можем вычислять результирующую матрицу построчно. Чтобы вычислить одну строку выходной матрицы, нам нужно прочитать две строки входной матрицы - (12Кб).
Отсюда пишем алгоритм:
- Код: Выделить всё
- var
 inp, outp: TFileStream;
 x: array [0..1, 0..999] of real;
 y: array [0..500] of real;
 m, n: Integer;
 k, l: Integer;
 i, j: Integer;
 begin
 inp := TFileStream.Create(inputFileName, fmOpenRead);
 outp := TFileStream.Create(outputFileName, fmCreate);
 
 // читаем размеры
 inp.ReadBuffer(m, sizeof(m));
 inp.ReadBuffer(n, sizeof(n));
 
 // вычисляем размеры выходной матрицы
 k := m div 2;
 l := n div 2;
 
 // запишем в выходной поток размеры результирующей матрицы
 outp.WriteBuffer(k, sizeof(k));
 outp.WriteBuffer(l, sizeof(l));
 
 // цикл по строкам внешней матрицы
 for i := 0 to k-1 do
 begin
 // читаем две строки входной матрицы
 inp.ReadBuffer(@x[0], n * sizeof(x[0,0]);
 inp.ReadBuffer(@x[1], n * sizeof(x[0,0]);
 
 // вычисляем строку выходной матрицы
 for j := 0 to l-1 do
 y[j] := (x[0, 2*j] + x[0, 2*j+1] + x[1, 2*j] + x[1, 2*j+1]) / 4;
 
 // Записываем строку выходной матрицы
 oup.WriteBuffer(@y[0], l * sizeof(y[0]));
 end;
 
 inp.free;
 outp.free;
 end;
 
Пушу без проверки, потому могут быть ошибки - главное суть - читам из потока пару строк, вычисляем результирующую строку и записываем в поток результат. Алгоритм обрабатывает матрицу размером до 6Гб, но расходует при этом в пределах 20 Кб под буферы. Нужно только придумать алгоритм, возможно нужно изменить формат входных данных, или считать ячейки с датчиков в каком-то особом порядке...
опять всё от задачи зависит... например, чтобы перемножить две матрицы, то будет проще, если вторая матрица уже транспонирована...