Информация об изменениях

Сообщение Re[13]: 2D-Linq и оптимизация цифровых фильтров - 3 от 04.07.2018 7:52

Изменено 04.07.2018 8:12 vdimas

Re[13]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:

S>Можно всё же в студию полное тело метода FourNeighborAverage?

S>Можете, если хотите, сделать его generic с where T: Struct, IArray2d<T>.

Разумеется генерик, ради ж этого всё.
Без студии:
void FourNeighborAverage<T>(T array) where T : struct, IArray2d<int>
{
    for(int y = 1, dy = array.DY - 1; y < dy; y++)
    for(int x = 1, dx = array.DX - 1; x < dx; x++)
            array[x, y] = array[x-1, y] + array[x+1, y] + array[x, y-1] + array[x, y+1];
}


Что здесь "так" в сравнении с твоим вариантом?
Здесь прикладное "знание" об алгоритме содержится в самом алгоритме, вот тут: int x = 1, DX = array.dx — 1.

В твоём же алгоритме такие "знания" необходимо каким-то образом передавать в сам абстрактный индексер.
Мой индексер получается более простым и универсальным — это просто абстракция некоторой матрицы.

Учитывая новый ref-return, можно попробовать пойти еще дальше:
[cs]
interface IArray2d<T> {
    ...
    ref T this[int x, int y] { get; } // только геттер
}
...
unsafe void FourNeighborAverage(T array) where T : struct, IArray2d<int>
{
    int dx = array.DX;

    for(int y = 1, dy = array.DY - 1; y < dy; y++) {
        fixed(int* current = array[1, y])
        fixed(int* end = array[dx, y])
        fixed(int* it1 = array[0, y])
        fixed(int* it2 = array[2, y])
        fixed(int* it3 = array[1, y - 1])
        fixed(int* it4 = array[1, y + 1]) {
            int* c = current, _1 = it1, _2 = it2, _3 = it3, _4 = it4;
            while(c < end)
                *c++ = *_1++ + *_2++ + *_3++ + *_4++;
        }
    }
}


Т.е. пусть Span<T> указывает на "область" длиной в одно значение, т.е. эдакий трюк ввиду того, что новый Core-фреймворк знает конкретно тип Span "в лицо".

Не, знаю, стоит ли напоминать, что в алгоритмах обработки изображений почти всегда присутствует параметр stride, который задаёт "шаг" между строками в физической памяти. Этот параметр можно загнать в конкретную реализацию IArray2d, т.е. можно побить изображение на области в том числе вертикально, т.е. распараллелить работу произвольных алгоритмов.


S>Меня интересует не "индексер" (предоставленный, потенциально, библиотекой), а полный код, который должен писать прикладной программист.


А другой программист должен будет еще этот код читать, верно?
Re[13]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:

S>Можно всё же в студию полное тело метода FourNeighborAverage?

S>Можете, если хотите, сделать его generic с where T: Struct, IArray2d<T>.

Разумеется генерик, ради ж этого всё.
Без студии:
void FourNeighborAverage<T>(T array) where T : struct, IArray2d<int>
{
    for(int y = 1, dy = array.DY - 1; y < dy; y++)
    for(int x = 1, dx = array.DX - 1; x < dx; x++)
            array[x, y] = array[x-1, y] + array[x+1, y] + array[x, y-1] + array[x, y+1];
}


Что здесь "так" в сравнении с твоим вариантом?
Здесь прикладное "знание" об алгоритме содержится в самом алгоритме, вот тут: int x = 1, DX = array.dx — 1.

В твоём же алгоритме такие "знания" необходимо каким-то образом передавать в сам абстрактный индексер.
Мой индексер получается более простым и универсальным — это просто абстракция некоторой матрицы.

Учитывая новый ref-return, можно попробовать пойти еще дальше:
[cs]
interface IArray2d<T> {
    ...
    ref T this[int x, int y] { get; } // только геттер
}
...
unsafe void FourNeighborAverage(T array) where T : struct, IArray2d<int>
{
    int dx = array.DX;

    for(int y = 1, dy = array.DY - 1; y < dy; y++) {
        fixed(int* current = array[1, y])
        fixed(int* end = array[dx, y])
        fixed(int* it1 = array[0, y])
        fixed(int* it2 = array[2, y])
        fixed(int* it3 = array[1, y - 1])
        fixed(int* it4 = array[1, y + 1]) {
            int* c = current, _1 = it1, _2 = it2, _3 = it3, _4 = it4;
            while(c < end)
                *c++ = *_1++ + *_2++ + *_3++ + *_4++;
        }
    }
}


Не, знаю, стоит ли напоминать, что в алгоритмах обработки изображений почти всегда присутствует параметр stride, который задаёт "шаг" между строками в физической памяти. Этот параметр можно загнать в конкретную реализацию IArray2d, т.е. можно побить изображение на области в том числе вертикально, т.е. распараллелить работу произвольных алгоритмов.


S>Меня интересует не "индексер" (предоставленный, потенциально, библиотекой), а полный код, который должен писать прикладной программист.


А другой программист должен будет еще этот код читать, верно?