Здравствуйте, Qbit86, Вы писали:
V>>В твоей версии значение берется всегда, даже когда оно не нужно на очередной итерации. Q>Зато нельзя обратиться к Current, не позвав TryMoveNext().
Зато в TryMoveNext надо "что-то" в любом случае писать в out (пусть даже default), а там может быть довольно-таки большая структура.
Q>То есть их зависимость выражена синтаксически. В крайнем случае, можно добавить перегрузку TryMoveNext() без параметров. Q>Reset() я бы тоже выкинул.
Подход плюсовых итераторов более чист идеологически. ))
internal class Program
{
public static void IterateForward<T>(T[] data) {
for (var i = data.Begin(); i != data.End(); i++)
Console.WriteLine(i.Current);
}
public static void IterateBackward<T>(T[] data)
{
for (var i = data.RBegin(); i != data.REnd(); i++)
Console.WriteLine(i.Current);
}
private static void Main(string[] args) {
int[] array = {1, 2, 3};
IterateForward(array);
IterateBackward(array);
}
}
1. Проверка за выход диапазона на каждом шаге не нужна, а только по факту доступа к элементу.
2. Доступ к элементу происходит только когда требуется.
Схематично:
public interface IForwardIterator<T, TIterator> : IComparable<TIterator>, IEquatable<TIterator>
where TIterator : IForwardIterator<T, TIterator>
{
ref readonly T Current { get; }
void MoveNext();
}
public interface IRange<T, out TIterator>
where TIterator : IForwardIterator<T, TIterator>
{
TIterator Begin();
TIterator End();
}
public interface IBidirectionalIterator<T, TIterator> : IForwardIterator<T, TIterator>
where TIterator : IBidirectionalIterator<T, TIterator>
{
void MovePrev();
}
public interface IBidirectionalRange<T, out TIterator, out TReverseIterator> : IRange<T, TIterator>
where TIterator : IBidirectionalIterator<T, TIterator>
where TReverseIterator : IBidirectionalIterator<T, TReverseIterator>
{
TIterator Begin();
TIterator End();
TReverseIterator RBegin();
TReverseIterator REnd();
}
public struct RangeIterator<T> : IBidirectionalIterator<T, RangeIterator<T>>
{
private readonly ArraySegment<T> _data;
private int _index;
public RangeIterator(ReadOnlyMemory<T> data) {
MemoryMarshal.TryGetArray(data, out _data);
_index = 0;
}
internal RangeIterator(ReadOnlyMemory<T> data, int index) {
MemoryMarshal.TryGetArray(data, out _data);
_index = index;
}
public ref readonly T Current => ref _data.Array[_data.Offset + _index];
public void MoveNext() => _index++;
public void MovePrev() => _index--;
public bool Equals(RangeIterator<T> other) => CompareTo(other) == 0;
public int CompareTo(RangeIterator<T> other) {
if (_data.Array != other._data.Array)
throw new InvalidOperationException("Incomparable ranges");
return other._data.Offset + other._index - (_data.Offset + _index);
}
public override bool Equals(object obj) => throw new NotImplementedException();
public override int GetHashCode() => throw new NotImplementedException();
public static RangeIterator<T> operator ++(RangeIterator<T> it) {
it.MoveNext();
return it;
}
public static RangeIterator<T> operator --(RangeIterator<T> it) {
it.MovePrev();
return it;
}
public static bool operator ==(in RangeIterator<T> a, in RangeIterator<T> b) => a.CompareTo(b) == 0;
public static bool operator !=(in RangeIterator<T> a, in RangeIterator<T> b) => a.CompareTo(b) != 0;
public static bool operator <(in RangeIterator<T> a, in RangeIterator<T> b) => a.CompareTo(b) < 0;
public static bool operator >(in RangeIterator<T> a, in RangeIterator<T> b) => a.CompareTo(b) > 0;
public static bool operator <=(in RangeIterator<T> a, in RangeIterator<T> b) => a.CompareTo(b) <= 0;
public static bool operator >=(in RangeIterator<T> a, in RangeIterator<T> b) => a.CompareTo(b) >= 0;
}
public struct ReverseRangeIterator<T> : IBidirectionalIterator<T, ReverseRangeIterator<T>>
{
private readonly ArraySegment<T> _data;
private int _index;
public ReverseRangeIterator(ReadOnlyMemory<T> data) {
MemoryMarshal.TryGetArray(data, out _data);
_index = data.Length - 1;
}
internal ReverseRangeIterator(ReadOnlyMemory<T> data, int index) {
MemoryMarshal.TryGetArray(data, out _data);
_index = index;
}
public ref readonly T Current => ref _data.Array[_data.Offset + _index];
public void MoveNext() => _index--;
public void MovePrev() => _index++;
public bool Equals(ReverseRangeIterator<T> other) => CompareTo(other) == 0;
public int CompareTo(ReverseRangeIterator<T> other) {
if (_data.Array != other._data.Array)
throw new InvalidOperationException("Incomparable ranges");
return -(other._data.Offset + other._index) + _data.Offset + _index;
}
public override bool Equals(object obj) => throw new NotImplementedException();
public override int GetHashCode() => throw new NotImplementedException();
public static ReverseRangeIterator<T> operator ++(ReverseRangeIterator<T> it) {
it.MoveNext();
return it;
}
public static ReverseRangeIterator<T> operator --(ReverseRangeIterator<T> it) {
it.MovePrev();
return it;
}
public static bool operator ==(in ReverseRangeIterator<T> a, in ReverseRangeIterator<T> b) => a.CompareTo(b) == 0;
public static bool operator !=(in ReverseRangeIterator<T> a, in ReverseRangeIterator<T> b) => a.CompareTo(b) != 0;
public static bool operator <(in ReverseRangeIterator<T> a, in ReverseRangeIterator<T> b) => a.CompareTo(b) < 0;
public static bool operator >(in ReverseRangeIterator<T> a, in ReverseRangeIterator<T> b) => a.CompareTo(b) > 0;
public static bool operator <=(in ReverseRangeIterator<T> a, in ReverseRangeIterator<T> b) => a.CompareTo(b) <= 0;
public static bool operator >=(in ReverseRangeIterator<T> a, in ReverseRangeIterator<T> b) => a.CompareTo(b) >= 0;
}
public struct Range<T> : IBidirectionalRange<T, RangeIterator<T>, ReverseRangeIterator<T>>
{
private readonly ReadOnlyMemory<T> _data;
public Range(ReadOnlyMemory<T> data) => _data = data;
public RangeIterator<T> Begin() => new RangeIterator<T>(_data);
public RangeIterator<T> End() => new RangeIterator<T>(_data, _data.Length);
public ReverseRangeIterator<T> RBegin() => new ReverseRangeIterator<T>(_data);
public ReverseRangeIterator<T> REnd() => new ReverseRangeIterator<T>(_data, -1);
}
public static class RangeExtensions
{
private static Range<T> range<T>(ReadOnlyMemory<T> data) => new Range<T>(data);
private static Range<T> range<T>(Memory<T> data) => new Range<T>(data);
public static RangeIterator<T> Begin<T>(this T[] data) => range(data.AsMemory()).Begin();
public static RangeIterator<T> End<T>(this T[] data) => range(data.AsMemory()).End();
public static ReverseRangeIterator<T> RBegin<T>(this T[] data) => range(data.AsMemory()).RBegin();
public static ReverseRangeIterator<T> REnd<T>(this T[] data) => range(data.AsMemory()).REnd();
public static RangeIterator<T> Begin<T>(this ReadOnlyMemory<T> data) => range(data).Begin();
public static RangeIterator<T> End<T>(this ReadOnlyMemory<T> data) => range(data).End();
public static ReverseRangeIterator<T> RBegin<T>(this ReadOnlyMemory<T> data) => range(data).RBegin();
public static ReverseRangeIterator<T> REnd<T>(this ReadOnlyMemory<T> data) => range(data).REnd();
}
Re[30]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, IB, Вы писали:
V>>Это у тебя сейчас рвануло, как обычно. IB>Ты так смешно ведешься, что не возможно удержаться =)
Да, я помню, что с тобой разве что бесполезное ля-ля-ля разводить можно.
ОК.
V>>Иначе бы он не напорол ошибок еще в первом же сообщении. IB>Ошибок, кроме тебя, в этом топике пока никто не делал.
Ошибок было наделано масса в первом же сообщении и до сих пор никуда не делись.
IB>А тебе удалось посадить их пяток в одном сообщении, от алгоритмических до синтаксических.
Когда было сказано "схематично без студии"?
Да пелевать.
IB>И чем громче ты пытаешься перевести стрелки на Антона
Тем больше у тебя рвётся пукан, я уже понял.
Соболезную.
IB>тем заметнее становится, кто на самом деле налажал.
По-определению налажал тут тот, кто всем врёт в техническом плане и затем настойиво изворачивается.
Что мешало Синклеру поступить честно и самому оценить своё решение, чтобы не было нужды посторонним раскрывать суть происходящего: http://www.rsdn.org/forum/dotnet/7192415.1
Я думаю, что помешала врожденная слабость характера.
IB>А так как у тебя не хватает тормозов во время остановиться, то мы еще долго будем наблюдать за феерией "я вовсе не это имел ввиду", "да вы ни фига не понимаете" и "я тут один молодец", до тех пор, пока не надоест тебя стебать
Ты тоже слабак, коль не можешь признать очевидного.
Так шта, упражняйся сколько хочешь.
Когда опять слетишь с катушек, я с чувством полного удовлетворения назову происходящее своими именами, мне не долго.
V>>Скажи, неужели бока обещанного "решения" не были тебе видны еще с самого первого поста? IB>С самого первого твоего поста в этот топик, отчетливо видно следующее: IB>- ты не умеешь внимательно читать или намеренно интерпретировал контекст так, чтобы было с чем докопаться до собеседника.
Не до собеседника докопаться.
Вот в этом ты и слабак, что не можешь признать очевидного.
Опять старательно уходишь от ЛЮБЫХ технических деталей, только разводишь ля-ля-ля общими словами.
Все годы с тобой только так — сливаешь любой технический спор.
А конкретно в этой серии топиков всё выглядит так, будто код Синклера внимательно прочитал я один. ))
Где-то даже обидно за Синклера — человек старался...
IB>- ты намеренно скрываешь детали своих утверждений, чтобы потом оставалось пространство для маневра, а то как доходит до деталей, то сразу вылезают ошибки от которых сложно отмазаться.
И конечно, тебе не трудно будет уточнить каждое из 3-х утверждений в этом предложении?
V>>В отличие от синклера я как раз решил именно ту задачу — покрыл целый класс похожих алгоритмов. IB>Задача была сформулирована даже не Антоном, а alex_public.
Слышал я уже эти отмазки и уже отправлял тебя к твоим же словам в том топике.
Вы обсуждали целый класс алгоритмов, а alex_public привёл лишь пример такого алгоритма.
Разумеется, ради единственной решенной задачи весь эксперимент Синклера будет профанацией.
Продолжая тщательно замыливать этот момент ты неотвратимо сливаешь.
Так шта, просто смирись со своей участью.
IB>Антон эту задачу процитировал в самом первом сообщении. И при решении этой задачи ты конкретно на косячил.
Я эту задачу вообще не решал и не собирался.
Я демонстрировал "недоговорённости" в коде Синклера.
IB>И ни какие отмазки этот факт не замажут. Так что, друг мой, да, в твоем решении алгоритмические ошибки, как бы ты не изворачивался.
А где я предоставил готовое к тестам решение исходной задачи?
V>>Более того, ни в одном сообщении не указал, что у меня есть полный аналог кода Синклера, бо для соревнований нужны оба решения, ес-но, не только моё. IB>Для решения указаной задачи, чужой код не нужен.
Чужой код нужен был для сравнения.
Я сюда влез изначально с единственным замечанием — Синклер сравнивает не то и не с тем: http://www.rsdn.org/forum/dotnet/7187266.1 Как бы ты не пытался это замазать.
Так шта, я вынес "индексеры" отдельно и предлагаю сравнить код на linq с кодом на индексере.
В этом месте вам стало слабо и вы ожидаемо слились, строча теперь то, на что я отвечаю.
IB>Можешь ее решить красиво? Код в студию, посмотрим, оценим и если твой подход действительно будет удачнее — признаем твою правоту.
V>>Я наехал на Синклера за его нечестность. IB>Подозреваю, что тот Синклер в твоей голове с которым ты споришь, не имеет никакого отношения к Антону. Но то что тебе на самом деле просто "тон" не понравился, ты признался уже давно.
Понравился/не понравился — оставь это старушкам на скамейке.
Тем более, что ты делаешь оценочные суждения даже не от своего имени, а от имени другого коллеги.
Это уже звоночек, однако... ))
IB>Натурально, как дурная девица в критические дни =)
Оставлю сие для следующей итерации для пущей нажористости.
Давайте, мистер, смелее!
Публика в предвкушении.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Слишком сложно
Дык, я и хотел показать именно дефолтную инициализацию полей.
Эта семантика изменилась в последних компиляторах С++.
На некоторых поддерживаемых нами более ранних компиляторах такой инициализации нет.
Re[31]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали: V>С ними не так заход на новый круг. V>Разве ты не согласился еще, что обслуживание краевых эффектов является неотъемлимой частью алгоритма?
Какого именно? Того, который приведён вот здесь: https://rsdn.org/forum/dotnet/7188166.1
Здравствуйте, Sinclair, Вы писали:
V>>С ними не так заход на новый круг. V>>Разве ты не согласился еще, что обслуживание краевых эффектов является неотъемлимой частью алгоритма? S>Какого именно? Того, который приведён вот здесь: https://rsdn.org/forum/dotnet/7188166.1
Э-э-э... Алгоритм плох?
А кто нас, инженеров, вообще спрашивает?
А взять блур?
Поворот?
Линзу с вырожденными коэф.?
Циклический сдвиг изображения?
S>>>Не требовать же вручную единички прибавлять. V>>А если не единички? S>То не единички. S>Я же привёл пример: S>
S>from d in data select (d[0, -2]+d[0, -1]+d[0, 0]+d[0, 1]+d[ 0, 2])/5
S>
S>Какое именно место здесь непонятно?
Тогда поясни своё "не требовать же вручную единички прибавлять".
О чём была речь?
Я так понял, что ты предлагал не делать этого в теле самого алгоритма, мол, унутре Linq всё само должно.
Если так, то моё "а если не единички" читается как "а если алгоритм другой"?
Например, если надо циклически сдвинуть изображение?
И всё это на фоне тех моих уже сделанных замечаний, что в системе типов C# не так просто (если вовсе не невозможно) сделать "соседние" перегрузки твоему Select.
Re[34]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали: V>А взять блур?
Ну, вообще-то, c4 и есть blur. Как раз с ним-то всё проще всего. V>Поворот?
Вот для поворота сходу не могу придумать такой записи кода, которая была бы понятнее, чем просто код поворота.
V>Линзу с вырожденными коэф.?
Пример кода можно? V>Циклический сдвиг изображения?
Сейчас в коде зашита стратегия "скипать те ячейки, для которых фильтр вылезает за границы".
Для циклического сдвига достаточно будет научить код принимать альтернативные стратегии.
Типа
var c = from d in data.WithWrap() select d[-5,0];
V>Тогда поясни своё "не требовать же вручную единички прибавлять". V>О чём была речь? V>Я так понял, что ты предлагал не делать этого в теле самого алгоритма, мол, унутре Linq всё само должно.
Да, конечно. Оно не только должно, оно уже так и делает.
V>Если так, то моё "а если не единички" читается как "а если алгоритм другой"?
Какое неожиданное прочтение Особенно в свете надувания щёк типа "да я внимательнее всех читаю код и вижу его насквозь". V>Например, если надо циклически сдвинуть изображение?
См. выше. Давайте посмотрим на ваш вариант кода для циклического сдвига изображения — насколько он будет понятнее, чем мой.
V>И всё это на фоне тех моих уже сделанных замечаний, что в системе типов C# не так просто (если вовсе не невозможно) сделать "соседние" перегрузки твоему Select.
Не вижу этих замечаний.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[4]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали:
V>Правда, в этом сценарии span уже не нужен.
Вот именно. Он интересен (потенциально) для того, чтобы не лезть в unsafe и не пинить память, мешая GC.
Теоретически, Span<T> мог бы конструироваться из 2d-массивов — они внутри одномерные. У них даже свойство Length есть, чтобы при конструировании Span<> проверить границы.
Практически, проще вручную сгенерить unsafe-код, чем объяснять JIT-у при помощи Span<>, что во внутреннем цикле bounds check не нужен.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[32]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:
V>>Правда, в этом сценарии span уже не нужен. S>Вот именно. Он интересен (потенциально) для того, чтобы не лезть в unsafe и не пинить память, мешая GC.
Ты мешаешь GC только если запинил мелкие объекты, бо крупные объекты (как наши массивы под изображения) выделяются из неуплотняемой кучи.
Ну и, на стеке если, то пин бесплатный в затратах, в отличие от GCHandle.
S>Теоретически, Span<T> мог бы конструироваться из 2d-массивов — они внутри одномерные.
Теоретически может играть рояль выравнивание, т.е. каждая новая строка могла быть выровнена.
Поэтому, для многомерных массивов генерятся методы-акцессоры.
Хотя да, для конкретной архитектуры местный JIT мог бы генерить прямой доступ по смещению и не было бы всего этого спора. ))
S>Практически, проще вручную сгенерить unsafe-код, чем объяснять JIT-у при помощи Span<>, что во внутреннем цикле bounds check не нужен.
А почему именно сгенерить?
Ты же применил активный обход массива, т.е. можно было прямо выйти на unsafe через обычный исходник.
Re[35]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Ikemefula, Вы писали:
V>>Т.е. молодец посредь овец? I>А ты, непростой. Чем тебе ado.net не угодил ?
Кратко если — всем.
Я когда-то два найденных бага MS SQL-драйвера им отправлял, поправили в один из патчей.
А вообще — это всё ужас, летящий на крыльях ночи, в СВ есть эпическое обсуждение на эту тему. ))
Re[36]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, Sinclair, Вы писали:
V>>А взять блур? S>Ну, вообще-то, c4 и есть blur.
Ага, байт — это тоже число.
Но от double уж слишком отличается. ))
S>Как раз с ним-то всё проще всего.
С такими натяжками запросто, ес-но.
А для обобщённого блура требуется или указывать цвет "бесконечности" или продлевать крайние пиксели изображения (на выбор).
V>>Поворот? S>Вот для поворота сходу не могу придумать такой записи кода, которая была бы понятнее, чем просто код поворота.
Но для этого кода всё-равно ведь нужен эффективный доступ к 2D-массиву, не?
Далее.
Что там насчёт расположения строк в памяти?
Последовательно в памяти идут значения последнего индекса в массиве, т.е. запись array[y, x] не самая удобная, т.е. хелпер-индексер в любом случае был бы полезен, который переводил бы индексирование в более привычную нотацию array[x, y].
V>>Линзу с вырожденными коэф.? S>Пример кода можно?
Частным случаем является эффект "рыбий глаз", ищется легко.
V>>Циклический сдвиг изображения? S>Сейчас в коде зашита стратегия "скипать те ячейки, для которых фильтр вылезает за границы". S>Для циклического сдвига достаточно будет научить код принимать альтернативные стратегии.
В реальной разработке у тебя будет фактически по одной стратегии на один алгоритм.
И разделения на "системного" и "прикладного" программиста (как ты предполагал) — не будет.
По крайней мере в этой реальности так не бывает. ))
S>Типа S>var c = from d in data.WithWrap() select d[-5,0];
При готовой такой "стратегии" тело цикла тоже не будет архисложным: dst[x, y] = src[x-5, y].
V>>Я так понял, что ты предлагал не делать этого в теле самого алгоритма, мол, унутре Linq всё само должно. S>Да, конечно. Оно не только должно, оно уже так и делает.
Я знаю что он уже делает, именно с этой незамутнёности и улыбаюсь.
Т.е., под впечатлением некоего одного алгоритма ты объявил некую стратегию обслуживания вылета индексов за границы дефолтной.
В реальной разработке сходу получил бы от коллег по шапке за такие странности.
При повторном проявлении подобных заскоков был бы отлучён насовсем от разработки подобных вещей, делов-то.
Это на форуме можно развлекаться, понятное дело, а за деньги подход чуть другой.
V>>Если так, то моё "а если не единички" читается как "а если алгоритм другой"? S>Какое неожиданное прочтение
Так и есть, поднадоедаешь своей недогадливостью, начистоту если.
У нас всегда неравнозначное общение выходит.
С первого раза не воспринимаешь и половины.
S>Особенно в свете надувания щёк типа "да я внимательнее всех читаю код и вижу его насквозь".
Тю.
Да я вообще тут единственный, кто твой код хоть как-то прочитал. ))
И попридержи, плиз, при себе весь этот информационный мусор насчёт "надувать щёки", "что-то сделать в лужу" и прочее.
Тоже этим поднадоел за все годы.
V>>Например, если надо циклически сдвинуть изображение? S>См. выше. Давайте посмотрим на ваш вариант кода для циклического сдвига изображения — насколько он будет понятнее, чем мой.
И опять самому не?
А как ты вообще работу свою работаешь?
И как ты с коллегами технические решения обсуждаешь?
Или с тобой их, рискну предположить, особо не обсуждают?
С тобой же никогда нет контакта, нет понимания, не видно даже желания понимать.
Всегда абстрактное зеро и упоротость на ровном месте.
Таким работникам можно лишь дать что-то ковырять в гордом одиночестве.
V>>И всё это на фоне тех моих уже сделанных замечаний, что в системе типов C# не так просто (если вовсе не невозможно) сделать "соседние" перегрузки твоему Select. S>Не вижу этих замечаний.
Ты оценку тому посту ставил, т.е. видел.
Ну или поставил оценку не читая, тут я ХЗ.
Re[37]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали:
V>>>Т.е. молодец посредь овец? I>>А ты, непростой. Чем тебе ado.net не угодил ?
V>Кратко если — всем. V>Я когда-то два найденных бага MS SQL-драйвера им отправлял, поправили в один из патчей. V>А вообще — это всё ужас, летящий на крыльях ночи, в СВ есть эпическое обсуждение на эту тему. ))
Что в дотнете работает быстрее адо?
Re[36]: 2D-Linq и оптимизация цифровых фильтров - 3
Здравствуйте, vdimas, Вы писали: V>Ага, байт — это тоже число. V>Но от double уж слишком отличается. ))
И что?
V>С такими натяжками запросто, ес-но. V>А для обобщённого блура требуется или указывать цвет "бесконечности" или продлевать крайние пиксели изображения (на выбор).
Или на лету модифицировать ядро фильтра для краёв. Дальше что?
Как раз в linq подходе я могу всё это сделать. При этом код останется читаемым.
А попытка закатить солнце при помощи ручного unsafe превратится в неподдерживаемые макароны уже при адаптации c4.
V>>>Поворот? S>>Вот для поворота сходу не могу придумать такой записи кода, которая была бы понятнее, чем просто код поворота. V>Но для этого кода всё-равно ведь нужен эффективный доступ к 2D-массиву, не?
Ну, я в своё время видел код поворота, написанный для win95 одним мальчиком-фанатом. Там внешний цикл менял код внутреннего цикла, чтобы сравнения указателя происходили не с регистром, а с константой.
Регистров ему там не хватало. "Эффективный доступ" к 2d-массиву — это, естественно, никакой не _data[x*w+y], а прямая манипуляция указателями. Требовать её в 2018 году от прикладного программиста — моветон.
Скорее мы отдадим ему готовый метод Rotate(double angle), а что там внутри — не его забота.
V>Далее. V>Что там насчёт расположения строк в памяти? V>Последовательно в памяти идут значения последнего индекса в массиве, т.е. запись array[y, x] не самая удобная, т.е. хелпер-индексер в любом случае был бы полезен, который переводил бы индексирование в более привычную нотацию array[x, y].
Это вопрос обозначений. Да, индексер штука в чём-то полезная. Но при этом код linq, который я написал, работает примерно на 30% быстрее, чем код с индексером вокруг линейного массиаа.
Что вполне предсказуемо — "индексер" делает одну проверку вместо двух, при этом жертвуя корректностью. Если его заставить бросать исключение, получив [10,-1], то его скорость сразу же упадёт до родной в дотнете.
А код linq вычислителя не делает проверок вообще. Там же то же самое, что вы писали с fixed(), только корректное, и автоматически учитывает размер переданного ядра.
V>Частным случаем является эффект "рыбий глаз", ищется легко.
Это вот это что ли? https://rsdn.org/forum/alg/191672.1
V>В реальной разработке у тебя будет фактически по одной стратегии на один алгоритм.
Я не понимаю, что здесь значит "алгоритм".
Алгоритм — это "пошаговая инструкция". с4 в виде linq — это не алгоритм, это спецификация.
Алгоритм — это конкретный способ перебора ячеек. Он в данном случае скрыт от пользователя. Поэтому я свободен менять его так, как мне вздумается.
V>И разделения на "системного" и "прикладного" программиста (как ты предполагал) — не будет. V>По крайней мере в этой реальности так не бывает. ))
Очень странно. А в том топике, откуда выросла эта идея, вовсю показывают библиотеки video++ и Eigen, показывая чёткое разделение между прикладниками и системщиками.
S>>Типа S>>var c = from d in data.WithWrap() select d[-5,0];
V>При готовой такой "стратегии" тело цикла тоже не будет архисложным: dst[x, y] = src[x-5, y].
И здесь стратегия зашита в "индексер", то есть в данные.
А в linq подходе я навешиваю её сверху. Потому что она является частью обработки, а не данных. Для c4 делать WrapAround — противопоказано, получится булшит. А для циклического сдвига (зачем бы он нам ни был нужен) — наоборот.
Для поворота надо будет применять стратегию substitute.
Можно, конечно, пойти по пути декораторов — типа "настоящие" данные у нас внутри, в виде, скажем, того же int[height*width], а "индексеры" навешиваются поверх.
Но я не вижу никаких преимуществ от этого, по сравнению с подходом linq, кроме увеличения размера "прикладной" части кода.
V>Я знаю что он уже делает, именно с этой незамутнёности и улыбаюсь.
Тогда откуда все эти вопросы про то, что там будет с краевыми эффектами?
V>Т.е., под впечатлением некоего одного алгоритма ты объявил некую стратегию обслуживания вылета индексов за границы дефолтной.
Я просто решал ровно задачу, поставленную коллегой. Запороть каёмку был его выбор. И он был сделан явно потому, что нормальная реализация c4 фильтрации выглядит на "простом и понятном коде обхода массива" как нечитаемая и неподдерживаемая лапша. Поэтому в "императивном подходе" мы по-бырому решили пожертвовать корректностью в пользу простоты.
V>В реальной разработке сходу получил бы от коллег по шапке за такие странности.
Я всего лишь показал пример. Это же не коммерческая библиотека, которая должна покрывать 5000 сценариев. Это просто иллюстрация того, что
А) линк — это вовсе не только перечисления и списки. Вот, постарались люди максимально неподходящую задачу придумать — упс! внезапно оказалось, что и в ней у linq всё хорошо.
Б) красота линка вовсе не обязательно связана с performance penalty. Внезапно оказывается, что он ещё и быстрее "идиоматического" кода. V>Это на форуме можно развлекаться, понятное дело, а за деньги подход чуть другой.
Естественно. За деньги бы я покрыл гораздо больше вариантов. V>У нас всегда неравнозначное общение выходит.
Конечно. Потому что я пишу строго по делу, а в ответ — булшит, передёргивания, подмена задачи, обвинения непойми в чём. V>И опять самому не?
Не. Зачем я буду делать вашу работу? V>А как ты вообще работу свою работаешь?
Отлично работаю. Благодарности, премии, повышения по службе. Спасибо за интерес. V>И как ты с коллегами технические решения обсуждаешь?
Очень просто. Для начала я стараюсь увидеть, в чём решения. А не придумать самостоятельно что-то по мотивам, недослушав и недопоняв, и тут же это критиковать.
Тот код, который я себе представил по вашему описанию, мне не нравится категорически. Но вместо того, чтобы сразу написать по результатам телепатического анализа "да говно у вас код, медленный и нечитаемый", я сдерживаюсь, в надежде, что вы вдруг напишете реально хороший и красивый код, до которого я просто не додумался.
V>>>И всё это на фоне тех моих уже сделанных замечаний, что в системе типов C# не так просто (если вовсе не невозможно) сделать "соседние" перегрузки твоему Select. V>Ты оценку тому посту ставил, т.е. видел.
Это вот это что ли "замечания"???
Всё-таки, генерики дотнета — это не генерики в полноценном смысле этого слова, т.к. не отвечают привычным требованиям генериков, бо их ограничения не входят в сигнатуры генерик-типов и методов. Это какая-то слаботипизированная хрень по мотивам якобы генериков. Сто процентов за пару вечеров на коленке налабали.
Работать с ними страшно неудобно как в сравнении с обычными типизированными генериками, так и в сравнении с полностью нетипизированными шаблонными параметрами в плюсах.
Даже взять твои рассуждения в первом же посте этой серии — ведь хорошо же видно, что надо еще и ПРИДУМАТЬ, как раскидать абстракции и каким идентификаторам какие ответственности назначить. ПРИДУМАТЬ тут капсом, бо простого/естественного назначения ответственностей не получается из-за мгновенно возникающих конфликтов или неподдерживаемых языком конструкций. ))
Или кроме этого набора слов было что-то более конкретное?
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Здравствуйте, Sinclair, Вы писали:
S>Регистров ему там не хватало. "Эффективный доступ" к 2d-массиву — это, естественно, никакой не _data[x*w+y], а прямая манипуляция указателями. Требовать её в 2018 году от прикладного программиста — моветон. S>Скорее мы отдадим ему готовый метод Rotate(double angle), а что там внутри — не его забота.
А кого это забота?
Ты о ком вообще говоришь?
V>>Далее. V>>Что там насчёт расположения строк в памяти? V>>Последовательно в памяти идут значения последнего индекса в массиве, т.е. запись array[y, x] не самая удобная, т.е. хелпер-индексер в любом случае был бы полезен, который переводил бы индексирование в более привычную нотацию array[x, y]. S>Это вопрос обозначений.
Это вопрос работы непосредственно с представлением изображений в памяти.
S>Да, индексер штука в чём-то полезная. Но при этом код linq, который я написал, работает примерно на 30% быстрее, чем код с индексером вокруг линейного массиаа.
Помимо линейного массива было предложено еще 3 варианта индексера.
S>Что вполне предсказуемо — "индексер" делает одну проверку вместо двух, при этом жертвуя корректностью. Если его заставить бросать исключение, получив [10,-1], то его скорость сразу же упадёт до родной в дотнете.
Вот именно что "если".
А если мы циклически сдвигаем изображение (по диагонали или даже под произвольным углом) и внутри индексера берется по модулю от размерности, то скорость не упадёт.
S>А код linq вычислителя не делает проверок вообще. Там же то же самое, что вы писали с fixed(), только корректное, и автоматически учитывает размер переданного ядра.
Ничего "автоматического" я там не увидел, там тоже написанный человеком, а не машиной, код, только написанный самым неуклюжим из всех доступных способов.
В реальной работе такое использовать нельзя.
V>>И разделения на "системного" и "прикладного" программиста (как ты предполагал) — не будет. V>>По крайней мере в этой реальности так не бывает. )) S>Очень странно.
Это потому что ты всю жизнь обитал на другой стороне Луны.
Программист или способен реализовать алгоритмы обработки изображений, или нет.
Третьего в этой реальности даже не рассматривается.
S>А в том топике, откуда выросла эта идея, вовсю показывают библиотеки video++ и Eigen, показывая чёткое разделение между прикладниками и системщиками.
video++ не смотрел.
Eigen — унылое тормознутое г-но, написанное классическим прикладником.
Достаточно посмотреть на способ упаковки операций в списки и последующего интерпретирования этих списков.
Ничего смешнее в этой области еще не видел.
А не, вру, видел — WPF так же работает.
V>>При готовой такой "стратегии" тело цикла тоже не будет архисложным: dst[x, y] = src[x-5, y]. S>И здесь стратегия зашита в "индексер", то есть в данные.
Да, поэтому погоня за экономией единиц символов в теле цикла — дурь.
Т.е. дурью является зашивание в индексер конкретных стратегий.
Индексер должен давать максимально эффективный доступ, не мешая при этом произвольным манипуляциям.
S>А в linq подходе я навешиваю её сверху. Потому что она является частью обработки, а не данных.
Это потому что у тебя с формулировкой задач проблемы.
Поэтому проблемы с их решением и анализом полученного решения.
Я тебе несколько раз называл важные с т.з. дизайна ПО "маркеры" — ты же не реагируешь.
Ну, всё ясно.
Я ХЗ уже как на пальцах объяснять, что раскидывая самые важные части прикладного алгоритма по далёким (в коде) друг от друга частям программы, ты поступаешь как вредитель.
Из реальных проектов всю эту дурь выжигают калённым железом сразу по обнаружении.
Там же на ней красным по-белому написано: "это я так поиграться решил".
S>Для c4 делать WrapAround — противопоказано, получится булшит.
Да плевать конкретно на c4.
Он приведён лишь как пример алгоритма, в котором требуется некая относительная адресация, т.е. относительно текущего элемента.
Включи хоть раз голову, да проанализируй, что у тебя получилось:
— реализация поверх лишь двумерного массива;
— вероятнее всего поданное изображение будет представленно совершенно иначе;
— как распараллелить обработку? побить в том числе вертикально?
— сколько всего требуется аналогичных реализаций для разных представлений изображения? если всего одно уже выглядит страшно? какова цена размножения решения?
Я ХЗ как можно было убить на это столько времени и не выйти на простую абстракцию, примеры которых я показал, назвав их "индексерами"?
S>Для поворота надо будет применять стратегию substitute.
Для поворота используется простейшая формула, которая прекрасно работает с абстракцией двумерного массива.
А ты опять предлагаешь детали прикладного алгоритма распихать по разным частям ПО, увеличивая связанность и уменьшая сцепление.
Налицо отсутствие навыков анализа решений.
Решений всегда более одного.
Их даже всегда больше двух. ))
Исскуство инженерии состоит в умении найти максимально полное множество решений, проанализировать их, и сделать осознаный выбор.
Ты не показываешь ни первого, ни второго, ни третьего.
S>Можно, конечно, пойти по пути декораторов — типа "настоящие" данные у нас внутри, в виде, скажем, того же int[height*width], а "индексеры" навешиваются поверх. S>Но я не вижу никаких преимуществ от этого, по сравнению с подходом linq, кроме увеличения размера "прикладной" части кода.
Кошмар.
Сами рассуждения — сплошной кошмар. ))
V>>Я знаю что он уже делает, именно с этой незамутнёности и улыбаюсь. S>Тогда откуда все эти вопросы про то, что там будет с краевыми эффектами?
Ну мне как-то до последнего не верилось, что ты настолько далёк от программирования как такового.
Вроде языком программирования владеешь, я ХЗ в общем.
Оно-то в реальной работе когда такие огрехи замечаешь, то реакция предсказуемая: "а, точно! прошляпил малость, сейчас придумаем как доработать".
Т.е. к реакции в духе "а? что? кто здесь?" я был не готов. ))
Кошмар.
V>>Т.е., под впечатлением некоего одного алгоритма ты объявил некую стратегию обслуживания вылета индексов за границы дефолтной. S>Я просто решал ровно задачу, поставленную коллегой. Запороть каёмку был его выбор. И он был сделан явно потому, что нормальная реализация c4 фильтрации выглядит на "простом и понятном коде обхода массива" как нечитаемая и неподдерживаемая лапша.
Думаешь, твоё решение читабельней? ))
S>Поэтому в "императивном подходе" мы по-бырому решили пожертвовать корректностью в пользу простоты.
В реальных алгоритмах обработки изображений, если по характеру алгоритма ожидаются кравевые эффекты, то они обслуживаются отдельной частью алгоритма.
"Лапша" тут может быть лишь от попыток свалить все части алгоритма в один цикл.
Разбей алгоритм на несколько частей:
— безопасное, максимально эффективное тело без краевых эффектов;
— проход по краевым эффектам.
Это наилучший подход к таким вещам.
V>>В реальной разработке сходу получил бы от коллег по шапке за такие странности. S>Я всего лишь показал пример. Это же не коммерческая библиотека, которая должна покрывать 5000 сценариев. Это просто иллюстрация того, что S>А) линк — это вовсе не только перечисления и списки.
Мде?
Наоборот, ты лишний раз показал, что это только перечисления и списки.
Что при попытке делать "что-то еще", "оно" прибивается гвоздями к конкретному алгоритму, т.е. является грубой архитектурной ошибкой сразу по двум основным метрикам ПО.
S>Вот, постарались люди максимально неподходящую задачу придумать — упс! внезапно оказалось, что и в ней у linq всё хорошо.
Для кого внезапно, для кого нет. ))
Отрасль с этим Linq подробно разобралась еще лет 10 назад.
Ты начни туда прикручивать where, например, сделать c4 только для абсолютно чёрных точек.
Или сделай из изображения последовательность центральных точек по Вороному.
Помнишь я говорил тебе о конфликте сигнатур?
Похоже ты так и не понял этого замечания. ))
Так вот, "заняв" целиком и полностью сигнатуру Select реализацией с активным возвратом результата, ты обрубил целый пласт алгоритмов.
S>Б) красота линка вовсе не обязательно связана с performance penalty. Внезапно оказывается, что он ещё и быстрее "идиоматического" кода.
Это ложь. Он не быстрее.
Что помешало тебе применить все свои трюки к "идиоматическому" коду, чтобы сравнение вышло спортивным?
V>>Это на форуме можно развлекаться, понятное дело, а за деньги подход чуть другой. S>Естественно. За деньги бы я покрыл гораздо больше вариантов.
Без конфликтов сигнатур?
Ты первый раз, что ле, глубоко копаешь Линк? ))
Ну, поупражняйся еще.
Для прочистки сознания, такскаать.
V>>У нас всегда неравнозначное общение выходит. S>Конечно. Потому что я пишу строго по делу
Ты пишешь НЕ строго по делу.
S>а в ответ — булшит, передёргивания
В ответ справедливые технические замечания, на которые у тебя истерика.
S>подмена задачи
Подмена задачи случилась у тебя.
А я лишь вытащил на свет божий всё это грязное бельё с подменой задачи. ))
Это ведь ты подменил эксперимент по оценке скорости работы линка на эксперимент по ускорению доступа к двумерному массиву.
Вопрос в силе — при чём тогда вообще линк?
Ты за кого окружающих держишь, эй?
S>обвинения непойми в чём.
Обвинения в силе.
Мухлёжь.
Попытка продать одно в решение в упаковке из под другого.
На простую просьбу "а давай-ка посмотрим на суть решение, т.е. развернём упаковку" — паника, переходы на личности и прочий мусор.
А почему так?
Потому что слишком пафосно выступил в первом же сообщении.
Проще надо быть. И честнее.
Тогда все вопросы прошли бы в рабочем порядке, без всей этой нелепой нервозности.
V>>И опять самому не? S>Не. Зачем я буду делать вашу работу?
Её можно проделать мысленно.
Или можно не делать, если настрой заведомо неконструктивный. ))
V>>А как ты вообще работу свою работаешь? S>Отлично работаю. Благодарности, премии, повышения по службе. Спасибо за интерес.
Я помню ты недавно делился некоторыми подробностями...
Ты изолирован от принятия технических решений.
Учитывая тщательно демонстрируемую поверхностность на фоне абсолютного неумения обсуждать СВОИ технические решения с кем бы то ни было — не удивительно.
V>>И как ты с коллегами технические решения обсуждаешь? S>Очень просто. Для начала я стараюсь увидеть, в чём решения. А не придумать самостоятельно что-то по мотивам, недослушав и недопоняв, и тут же это критиковать.
Во-во.
Критика решения воспринимается как личное оскорбление.
"Недослушав и недопоняв" — враки.
Тебя понимают более чем хорошо.
по опыту нашего многолетнего общения ровно наоборот — ты сам не стремишься вникнуть аргументы собеседника.
Тебе оно, как бы это помягче выразиться, не интересно.
Знаешь как про таких говорят опытные разработчики? — "его техническому мнению нельзя доверять".
Это обычно приговор. Сам человек этого не услышит, но обнаружить это легко косвенно — что бы ты ни пытался "протолкнуть" — оно почти никогда не "проталкивается".
Потому что клеймо необъективности — оно в нашем деле одно из самых суровых.
S>Или кроме этого набора слов было что-то более конкретное?
Что тебе не понятно во фразе "ограничения генериков не входят в сигнатуры генерик-типов и методов"?
Я в такие моменты обычно в растерянности — это ты опять придуряешься в своей неконструктивной манере или ДЕЙСТВИТЕЛЬНО не понимаешь, о чём речь?
Если придуряешься, то можешь считать себя клоуном.
Если действительно не понял, то трус и форумный хамло, который вместо простого "я тут недопонял" маскирует своё непонимание через нападки, нимало не смущаясь тем, что увеличивает градус нервозности. Со стороны не пробовал на такие закидоны смотреть? ))
Re[37]: 2D-Linq и оптимизация цифровых фильтров - 3