• Почему CLR при генерации Машиного кода не оптимизирует циклы?

    @daniil14056 Автор вопроса
    Василий Банников, а как их надо забанчмаркетить. Типа делать функцию из допустим 100 вызовов и xor с
    a^= *(long*)(ptrAddr | position);
    b^= *(long*)(ptrAddr | position);
    a^= *(long*)(ptrAddr | position);
    b^= *(long*)(ptrAddr | position);
    ... 100 раз
    return a+b;
    Но вот выше что-то мне подсказывает, что там будет распространение вычисленного выражения. и надо все сильнее и сильнее усложнять.
    или цикл, но мне не нравится что сам цикл времени добавляет

    У меня очень часто какой-то метод за 0 времени выполняется, я полагаю компилятор понял что метод бессмысленный и удалил из него все.
    Написано
  • Почему CLR при генерации Машиного кода не оптимизирует циклы?

    @daniil14056 Автор вопроса
    Василий Банников, а какой можно сделать пример вот для примера выше. прочесть long с байт массива.
    Почему у меня бенчмарк показывают разницу в 10 раз, то вообще метод за 0.000, а с разными параметрами полярный результат.
    ReadLongFromPtrLong | 13 | 0.1227 ns | 0.2736 ns | 0.1810 ns | 0.0000 ns | 11 B
    ReadLongFromPtr | 13 | 0.0506 ns | 0.0725 ns | 0.0432 ns | 0.0571 ns | 12 B

    ReadLongFromPtrLong | 64 | 0.0066 ns | 0.0240 ns | 0.0159 ns | 0.0000 ns
    ReadLongFromPtr | 64 | 0.2576 ns | 0.4030 ns | 0.2666 ns | 0.2262 ns

    ReadLongFromPtrLong | 80 | 0.2658 ns | 0.7905 ns | 0.4704 ns | 0.0424 ns
    | ReadLongFromPtr | 80 | 0.0357 ns | 0.1312 ns | 0.0780 ns | 0.0000 ns

    Разница в 5-10 раз во все стороны. Может такие маленькие методы нельзя мерить, хотя примеры из документации не особо больше
    Написано
  • Почему CLR при генерации Машиного кода не оптимизирует циклы?

    @daniil14056 Автор вопроса
    Василий Банников, а где про это прочитать, 100 раз. В jvm 10_000. слышал. читаю управление памятью в .NET для профессионалов, но там пока не нашел.
    Меня интересует кто считает вызовы, и сколько это отнимает времени. В откладке бегаю по инструкциям, и не могу найти.
    При том 100 раз, это как-то мало, что бы я замечал, допустим, по фасту, когда в голову придет что-то быстро замерить, я замеряю метод обычно так, где n под миллион-миллиард.
    Какие минусы у такого замера
    [noinlining]
    static int m(int n,Func<int> func,string msg){
          int sum=0;
          var s=Stopwatch.StartNew();
          for(int i=0;i<n;i++) 
              sum+=func(i);
          s.Stop;
          print(s.Elapsed.TotalNanosecunds/n,msg);
          return sum;
    }

    А Вот Бренчамрки как BenchmarkDotNet я их не понимаю, не доверяю или не понимаю что они выводят, мне кажется они весь код удаляют как бессмысленный.
    Если такой тест дает что-то понятное. То вот с BenchmarkDotNet разница в 10-1000 раз то где разница должна быть на скидку ну в 2 раза макс. Либо я не правильно делаю. К примеру как замерить
    unsafe byte* ptr;  // Nativememory.AllocAlligned();
        long ptrAddr; //= (long)ptr;
    
       [Benchmark(Description = "ReadUnaligned")] 
        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
       public long ReadUnaligned()
       {
           return Unsafe.ReadUnaligned<long>(ref buffer[position]) ;
        
       }
    
        [Benchmark(Description = "ReadLongFromPtrLong")]
        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
        public long ReadLongFromPtrLong()
        {
            unsafe
            {
                return *(long*)(ptrAddr | position);
            } 
        }
            [Benchmark(Description = "ReadLongFromPtr")]
            [MethodImpl(MethodImplOptions.AggressiveOptimization)]
            public long ReadLongFromPtr ()
            {
                unsafe
                {
                    return *(long*)( ptr + position);
                } 
            }

    Запускаю с разными стратегиями, жду час, получаю супер разные результаты. с разницей то в разы, то ни с какой.
    Написано
  • Почему CLR при генерации Машиного кода не оптимизирует циклы?

    @daniil14056 Автор вопроса
    Release
    А как прогнать код? Ну типа миллион раз вызвать в большой иерархии, вызовов. А после уже замерять. Ну это я по дефолту делаю.
    CLR разве не после второго вызова скомпилирует конечный код?

    А можно ли задать ли какие-то параметры компиляции, и главное куда если можно, а то Visual Studio только версию языка, целевую платформу и предлагает.
    Написано
  • Что за формат чисел в ассемблерных файлах 000ABC100h в конце 'h', конкретно как парсить?

    @daniil14056 Автор вопроса
    Основной вопрос не касается шарпа, а формата числе в ассемблерных файлах к примеру из https://godbolt.org/
    Нет, не могут. Только что просматривая трииллион строк диззасемблера нашел число 07f_ff_ff_ff_ff_ff_ff_ffh (без _) c "0" после чего 16 символов. и h на конце.
    А то так сложно будет определить для задачи написания дизассемблера call aaaaaaaaaaaaah это метка или число.
    Написано
  • Почему с отладкой нет ошибки, а без отладки есть?

    @daniil14056 Автор вопроса
    А что если t на самом низу стека, как первая переменная в программе, она в памяти зафиксирована там, или нет гарантии?
    Вот этот момент хочу уловить, стек может как-то уехать .
    Написано
  • Почему с отладкой нет ошибки, а без отладки есть?

    @daniil14056 Автор вопроса
    Сергей Водаков, это код примера. а не кода. Который вообще написан в форме тостера. Что бы как раз и рассмотреть эту ситуацию.
    Написано
  • IL генерация кода. Как загрузить в локальную переменную, константную ссылку на объект?

    @daniil14056 Автор вопроса
    VoidVolker, спс за библиотеку, только ща узнал, что смотрел лекции ее автора,
    а правильно ли я понимаю что вот пример выше можно написать только с помощью когенерации и невозможно даже на ассемблере. Поэкспериментировал, и вот так вот вычислить адрес, и вставить его быстрее чем, допустим там стояло this.Point.
    Написано
  • Почему с отладкой нет ошибки, а без отладки есть?

    @daniil14056 Автор вопроса
    Василий Банников, поле Test.tS.arr становится равным нулю само по себе. И только без откладки и то не всегда.
    Я исправил передачу в функцию на Struct* вместо ref Struct. Не понимаю. почему адрес меняется.
    Почему структура съезжает с стека, типа же она же на стеки инициализируется. но она точно съезжает, куда-то.
    Написано
  • IL генерация кода. Как загрузить в локальную переменную, константную ссылку на объект?

    @daniil14056 Автор вопроса
    VoidVolker, Я покопался и понял что у меня ошибка, к примеру получение адреса структуры
    var pointVar = il.DeclareLocal(typeof(Point*), true);
    Point p = new Point() { X = 1 };
    <b>il.Emit(OpCodes.Ldc_I8, (ulong)&p); </b>

    (ulong)&p не знаю, короче почему, но преобразование в (ulong) что-то ломает. Вот так работает. Я правда не понимаю какая разница, ведь long и ulong лишь разное отображение данных, биты то одинаковы.
    OpCodes.Ldc_I8, (long)&p 
    il.Emit(OpCodes.Conv_U);   
    //... дальше все ок
    //аналог         
    static unsafe void f()
            {
                ulong ptrp = 0x11111ffffffu; // значение будет вычислено при генерации 
                Point* ptr = (Point*)ptrp;
            }
    Написано
  • IL генерация кода. Как загрузить в локальную переменную, константную ссылку на объект?

    @daniil14056 Автор вопроса
    VoidVolker, я же написал. По адресу вызвать метод, или по адресу получить элемент.
    Это 1-3 магических инструкции наверное.
    Вот есть инструкция
    il.Emit(OpCode.LdStr, "HelloWorld); кладет строку, фактически только адрес на нее, строка это объект, значит должны быть команды, и для произвольного типа.

    Проблему я описал. Вот так в сто раз дольше чем
    int arr=new Random().Next()
    int arr=(Random*)address.Next()
    Написано
  • IL генерация кода. Как загрузить в локальную переменную, константную ссылку на объект?

    @daniil14056 Автор вопроса
    так и делаю, но он выдает дизасемблер, А мне нужна последовательность команд, Emit(OpCodes.fddf, arguments) вот эти Аргументы вообще нигде не написано,
    18 перезагрузок методов, и не понятно, к какому опкоду какая перезагрузка.
    И на сайте не всегда есть пример.
    Например вот такой код генерится, а как его в код перенести, у меня ошибки, вплоть до системных.
    Мне всего и надо понять как из ulong -> (structObj*)->RunMethod();
    .locals init (
                [0] valuetype C/Point& pinned   
            )
    IL_0000: ldarga.s p1
            IL_0002: conv.u
            IL_0003: conv.u8
            IL_0004: call void [System.Console]System.Console::WriteLine(uint64)
            IL_0009: ldsflda valuetype C/Point C::point
            IL_000e: stloc.0
            IL_000f: ldloc.0
            IL_0010: conv.u
            IL_0011: ldfld int32 C/Point::X
            IL_0016: call void [System.Console]System.Console::WriteLine(int32)
            // sequence point: hidden
            IL_001b: ldc.i4.0
            IL_001c: conv.u
            IL_001d: stloc.0
            IL_001e: ret

    struct Point{
              public int X;
          }  
        static Point point=new Point(){X=100};
        static unsafe void f(in int r, Point p1){
            ulong ptrp=(ulong)&p1;
            Console.WriteLine(ptrp);
           fixed(Point* ptr=&point){ 
      
            Console.WriteLine((ptr )->X); 
          }     
        }

    https://sharplab.io/#v2:C4LglgNgPgAgTARgAQFgBQMDMT...
    Написано
  • Как эмуляторы транслируют клиентский код в машинный?

    @daniil14056 Автор вопроса
    спс за ответ. Есть еще такой вопрос, все не пойму.
    Базовый блок заканчивается при инструкции чтения памяти, в вики то же написано. А ведь это почти каждая вторая инструкция. Как это решается. Тогда каждый блок будет из 1 команды почти.
    Либо же надо как-то взять и всю память как-бы отнять. Или логику поменять.

    Еще то же вопрос он так же к этому, проверка выхода за границы массива.
    Пример, Пройти в цикле по массиву и найти сумму элементов.
    Программа-> Компилятор -> 3 адр код на выходе -> ОптимизированныйИнтерпретор
    //  sum(byte* arr) 
    //      sum=0;
    //      for(int i=0;i<10;i++)
    //          sum+= arr[i];
    //      return sum;     
    // вариантик  на ходу , пример 3адр кода
    0:  load  maxReg 10
    1:  load  IterReg , 0
    2:  load  sumReg,  0
    3:  load  arrReg, r1
    4:  branchIfLess  IterReg, maxReg, "9:"
    5:  load valReg, [sumReg+iterReg]
    6:  add  sumReg, valReg
    7:  addi iterReg, 1 
    8:  branchIfLess r1, r2, "5:"
    9:  mov r1, sumReg
    10:  ret

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

    Я уже точно знаю, что если в метке "9" i < 10,. условие выполнилось, то и при след доступе к элементу arr[i] у меня не будет выход за предел массива.
    Но машина эмулирует память, и должна выдавать исключения при выходе за границу памяти. И она там не знает что вот там есть какой-то регистр, и какая-то инструкция до, уже выполнила проверку.
    Эмулятор имеет к примеру такую функцию чтения памяти, самый простой вариант.
    byte ReadByte(int address){
                 if(address<0 && address>maxAddress) ____();/// что-то там
                 return *(byte-*)mem+address;  
       } 
       // byte ReadByte(int address)=>   *(byte-*)mem+address;

    Короче if(...) функции явно лишняя, плюс ко всему, эта инструкция блок прервет.
    Вариант заменить ее закомментированным вариантом. Но не понимаю, как обнаружить, особенно если что-то посложнее, и архитектурное решения точно должно решить и первую проблему
    Написано
  • Как эмуляторы транслируют клиентский код в машинный?

    @daniil14056 Автор вопроса
    mayton2019, в процессе написания вопроса, часто что-то понимаю, ответ, порой сокращает время гугления. так как большинство терминов вообще не найти на русском.
    Написано
  • Как создатьListBox из toggleButton вплотную, в строку, без отступов?

    @daniil14056 Автор вопроса
    Я короче не знал, что есть отдельный элемент ItemsSource а делал эти элементы в List который там свою логику добавлял
    Написано
  • Как по массиву точкек нарисовать круг WPF? Из миллиона точек?

    @daniil14056 Автор вопроса
    Роман, для простоты. конечно там не круг
    Написано
  • Почему MouseMove не срабатывает?

    @daniil14056 Автор вопроса
    да, точно, почти всегда пишу transparent, а тут забыл, и потратил кучу времени не там ища).
    Написано
  • Что делает IEqualityComparer? Он вообще работает?

    @daniil14056 Автор вопроса
    а почему он не работает? Реализовал я его, уже триллионом миллиардов способов. и всех возможных комбинаций, включая все комбинации вместе IComparableICompare абстрактного класса EqualityComparer, а это овер 32 комбинаций, и не разу не попал в его методы в отладчике. или в c# 7.0 он не работает
    Написано
  • Как хешировать в хеш таблице узлы дерева?

    @daniil14056 Автор вопроса
    Забыл добавить.
    Каждый корневой узел состоит из уникального числа потомков. Если создается узел, всего с одним на самом вверху изменённым узлом, то он новый.
    Еще такие уловия, Из хеш-таблицы удалений не бывает, она только растет , то есть можно как-то запечатать.
    Каждый Хеш код Корневого узла создается на основе ?_функции от 2 его потомков.
    Задача, как можно гарантировано, знать, что этот хеш код не может совпадать, с одноуровневыми соседями. Что бы сделать только 3 проверки максимум.
    К примеру 2 16bit значений можно гарантированно уместить на 32bit. nodeA<<16 | nodeB; Вот короче как-то отсюда надо думать)
    А с 2мя -20bit уже так не получится, будут колизии, но возможно, для таких значений, мне нужно проверить на один уровень ниже просто. (Что особо не замедлит, так как на высоте 20 будет меньше в 16 раз меньше вызываться функция ContainsKey )
    Написано
  • Как сделать преобразование фурье для изображения по xy?

    @daniil14056 Автор вопроса
    Это понятно, там все что с пикселями, Я не понимаю. Вот что дальше то.
    "приступаю к фурье". а что на вход то идет, что в массивах x,y? И что на выходе я получаю.
    Вот для примера 4 пикселя, что в отладчики я увидеть должен в массиве x? Или в комплексном массиве Complex[]x?
    С одномерным то же не понимаю. Работает или нет., типа что я должен увидеть. Но и все библиотеки то же не работают. В общее не понимаю, как понять что все работает или нет.
    Вот тригонометрическую интерполяцию хорошо понимаю. И прочие аппроксимации.
    Я вот не понимаю, почему у меня, и у всех 10 библиотек что попробовал, не работает. Типа вот для функции я нахожу коэффициенты, а потом я для параметра x или t нахожу комплексное число типа точку[x,y], если я ее построю на графике, то получаю зикзаги. Вместо графика исходной функции.
    f(x)= Σ[a*cos(x*n)+i*b*sin(x*n)]


    А вот как сделать преобразования Фурье Спирали, к примеру? Какой-то кривой которая влево вправо вертится.
    Написано