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 Кб под буферы. Нужно только придумать алгоритм, возможно нужно изменить формат входных данных, или считать ячейки с датчиков в каком-то особом порядке...
опять всё от задачи зависит... например, чтобы перемножить две матрицы, то будет проще, если вторая матрица уже транспонирована...