• Почему RenderTargetBitmap долго отрисовывается?

    @AlexHell
    судя по информации что я нашел https://stackoverflow.com/questions/56582013/why-t...
    RenderTargetBitmap doesn't take advantage of hardware rendering

    т.е. простыми словами - он рендерит на CPU, и в отличие от GPU рендеринга (шейдерами в играх как вы приводите сравнение), CPU рендеринг очень медленный, и не предназначен для высокого FPS, а скорее для оффлайн обработки как в граф редакторе без видеокарты :)
    Ответ написан
    Комментировать
  • Как прервать поток c#?

    Это вообще правильно?

    Да, это правильно и это по сути единственный адекватный способ отмены долгоиграющих операций.
    Когда-то давно у потоков был метод Abort, но его удалили, тк его использование очень часто приводило к неприятным багам.
    Ну и пихать проверку cancellation token повсюду не обязательно.
    Поток вызывает 1 функцию библиотечную неуправляемого кода, как ее прервать?

    Безопасно - никак, если эта неуправляемая функция не предоставляет интерфейс для отмены.
    Даже если бы и был способ (тот же Abort), то прерывание неуправляемого кода очень вероятно приведёт к утечке ресурсов (в лучшем случае не будет освобождена динамическая память)
    Ответ написан
    Комментировать
  • Как нормализовать массив значений в цветовое представление?

    @Mercury13
    Программист на «си с крестами» и не только
    Уровень 1. Чёрно-белое.
    R, G, B = round((x−min)·255 / (max − min))

    Уровень 2. Градиент между цветом X и цветом Y.
    t = (x−min) / (max − min)
    R = round(R1·t + R2·(1−t))
    G и B аналогично.

    Уровень 3. Учёт гамма-кривой монитора. Тут работаем сразу в двух цветовых пространствах: линейном от 0 до 1, и sRGB от 0 до 255.
    gamma = 2,2 — sRGB состоит из линейного и степенного участка, но неплохо приближается real_brightness = channel_%^gamma
    invGamma = 1/gamma
    функция toLinear(v) := (v/255)^gamma
    функция toSrgb(q) := (q^invGamma)·255 — в общем, обратная
    linR1 = toLinear(R1)
    linR2 = toLinear(R2)
    t = (x−min) / (max − min)
    R = round(toSrgb(linR1·t + linR2·(1−t)))

    Уровень 3.1. 16-битная аппроксимация (если важна скорость). В общем, линейное цветовое пространство — не дробные от 0 до 1, а целые от 0 до 65535.
    функция toLinear(i) := round(((i/255)^gamma)·65535)
    массив toSrgb(q) := ((q/65535)^invGamma)·255 — записывается в виде массива на 65536 величин
    linR1 = toLinear(R1)
    linR2 = toLinear(R2)
    K = (65535 / (max − min)
    t = round((x−min) * K)
    R = toSrgb(((linR1·t) + linR2·(65535−t) + 127) >> 16)

    Уровень 4. Сложный градиент из нескольких цветов.
    Для этого например, t=0 — синий, t=⅓ — зелёный, t=⅔ — жёлтый, t=1 — красный.
    Тогда прикидываем, в какой промежуток попадает t, получаем, например, t1=(t−⅓)·3, и дальше по уровню 3.
    Ответ написан
    Комментировать
  • Масштабирование времени? Как рассчитать положение точки при ускорении времени?

    Griboks
    @Griboks
    Используйте скорость на каждой итерации для моделирования движения.
    Шаг 1:
    V+=1=0+1=1
    X+=V=0+1=1

    Шаг 2:
    V+=1=1+1=2
    X+=V=1+2=3


    А теперь, ускорим время в 10 раз, пусть шаг физического движка будет 10сек=1сек, То что будет

    Не забывайте, что ускорение масшиабируется вместе с временем.

    Поэтому обычно пишут
    V=V0×dt
    Где V0 - скорость в нормальном ходе времени.
    Ответ написан
    2 комментария
  • Где ошибка, как из рекурсии цикл сделать?

    @mvv-rus
    Настоящий админ AD и ненастоящий программист
    //...declarations and initializations omitted
               do
               {
                   //...some code omitted
                   if (j != i)
                   {
                       swap(i, j);
                       i = j; 
                   }
               } while (j != i);

    Не работает, потому что вы сначала присваете j значение i, если они не равны, а потом, в условии продолжения цикла, сравниваете их значения. Естественно, они будут равны и выход их цикла получится на первой же итерации. Проверять i==j как условие выхода из цикла надо чуть раньше, например, так:
    //...declarations and initializations omitted
               do
               {
                   //...some code omitted
                   if (j != i)
                   {
                       swap(i, j);
                       i = j; 
                   }
                   else break;
               } while (true);


    Ну, а что до второго вопроса, то в .NET, начиная с 6.0 есть класс System.Collections.Generic.PriorityQueue<TElement,...
    Ответ написан
    6 комментариев
  • Как найти минимальное число прохождений по автомату до конечного состояния с N вероятностью?

    wataru
    @wataru Куратор тега Математика
    Разработчик на С++, экс-олимпиадник.
    Есть простой трюк сильно упростить задачу: Измените переходы из "конечной" вершины - она теперь с вероятностью 100% будет вести только в саму себя. Таким образом, процесс хотя бы раз достигший вершины, навсегда в ней останется.

    А вопрос из задачи (если его понимать как: минимальное количество шагов, чтобы хотя бы раз посетить конечную вершину с вероятностью >99%) становится эквивалентен: минимальное количество шагов, чтобы быть в конечной вершине с вероятностью не меньше 99%.

    А тут уже надо найти минимальное число k, такое что соответствующее значение в матрице A^k было бы > 0.99. A тут - это матрица переходов.

    Можно или в тупую умножать матрицу саму на себя, пока значение в строке начальной вершины и столбце конечной вершины не станет достаточно большим. Это будет O(N^3*ответ). Или можно делать хитро: бинарным поиском перебирайте степень, а внутри логарифмическим возведением в степень считайте A^k. Это будет O(N^3*log(ответ)^2).
    Ответ написан
    Комментировать
  • Как реализовать виртуальный кеш, tlb?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как реализованы в kvm qemu virtualbox бош и другие

    В KVM -- никак, KVM использует фичу хостового процессора известную как 2-stage translation, при этом на первой стадии хостовый процессор выполняет трансляцию гостевого виртуального адреса в гостевой физический, аппаратно.

    В QEMU -- я тебе уже писал как, с деталями и ссылочками в код. Но ты вместо того чтобы задавать конкретные вопросы опять начинаешь говорить что там всё сложно и непонятно.

    Какой там алгоритм замещения(Или его там нету).

    В QEMU собственный TLB QEMU прямого отображения, в случае промаха единственная запись TLB в которой может быть отображение для искомого виртуального адреса замещается новой трансляцией. Зависящий от эмулируемой архитектуры TLB эмулирует детали архитектуры, тебе нужно выбрать конкретную архитектуру чтобы её обсуждать, иначе мы закопаемся среди разных вариантов.

    void* translate(int acid, int addr){

    Похож на реализацию собственного TLB QEMU, только там нет ASID и в качестве тега используются все биты виртуального адреса кроме младших (обычно младших 12, но может быть меньше, если у эмулируемой архитектуры есть страницы меньшего размера).
    Ответ написан
    Комментировать
  • Чем загрузчик в виртуальных процессорах отличается от реального? Какой жизненный цикл запущенной ОС на виртулальном?

    Melkij
    @Melkij
    PostgreSQL DBA
    Запуститься ли обычная ос на виртуальном процессоре(не понимаю как это протестировать. так как образы ос для виртуалок, чет немного другие, а что в них другого в этом вопрос)

    Есть разные варианты виртуализации.
    Если мы виртуализируем всё железо - это предназначено именно для запуска ОС, ничего не знающей о виртуализации. Но за виртуализацию всякой периферии (вроде дисков и сети) расплачиваемся снижением производительности.
    Можно не виртуализировать периферийные устройства - но тогда гостевая система должна уметь работать с такой периферией. Если ОС не знает как работать с диском - то она банально не сможет загрузиться.
    Может вся ОС быть в режиме паравиртуализации

    Точно не все, к примеру в qemu память выделяется динамически. А значит. Ram может расти. А в реальности, я не могу взять и RAM увеличить в 2 раза по команде. Значит есть инструкция, new которая берет и из неоткуда(с точки зрения вирт ос) берет память.

    https://en.wikipedia.org/wiki/Memory_ballooning
    Ядро гостевой ОС намеренно модифицировано и знает как попросить больше памяти у гипервизора.

    То что вы упускаете: виртуального процессора не существует.
    Управление памятью же... Хе-хе. Если не сильно ошибусь в исторический экскурс, то в прошлом году исполнилось уже 50 лет с тех пор как память в x86 перестала работать так наивно, как вы описали. https://en.wikipedia.org/wiki/Virtual_memory
    malloc гигабайтного куска памяти уже очень давно не даёт гигабайтный кусок непрерывных адресов в физической RAM. Фактически, malloc сейчас вообще не даёт память, а только обещает её дать позже. Куда и как эта память будет распределена по физической RAM - да фиг его знает, этим управляет операционная система. Виртуализация соответственно возводит сложность управления виртуальной памятью в квадрат. Это может быть как двойная работа - сначала гость в том что считает своей RAM распихивает всё что есть как нравится, затем гипервизор ничего не зная о алгоритмах управления памятью в госте распихивает занимаемую гостем память по своей виртуальной памяти. Или это может быть какая-то кооперация.
    Ответ написан
    Комментировать
  • Чем загрузчик в виртуальных процессорах отличается от реального? Какой жизненный цикл запущенной ОС на виртулальном?

    gbg
    @gbg
    Любые ответы на любые вопросы
    на виртуальном процессоре

    1. Современные системы виртуализации используют реальный процессор. Есть конечно и системы, которые эмулируют процессор программно, но это когда речь идет об эмуляции между архитектурами - например, код для ARM запускают на x86.
    2.
    так как образы ос для виртуалок, чет немного другие, а что в них другого в этом вопрос

    отличия в драйверах. "Обычная" ОС должна работать в виртуализации без проблем.
    3.
    А значит. Ram может расти.

    Не вполне верно. Верхний предел RAM задается при старте машины. RAM можно уменьшить, но не увеличить.

    Для современного процессора, выполнение гостевой ОС - это выполнение обычной программы, просто в какие-то моменты он перехватывает обращения к железу и подсовывает туда код гипервизора. Если же мы говорим о программной реализации процессора, то памятью может быть просто массив байтиков.
    Ответ написан
    Комментировать
  • Почему в с# в стуктурах с static void* ptr указателем этот указтаель не равен нулю при инициализации?

    // в откладке показывает TRUE, но как-будто false отрбатывает

    Предположу, что это просто глюк дебаггера. У меня он вообще не может прочитать значение Ptr и пишет вот что:

    Failed to read static field: Статическая переменная недоступна, поскольку еще не инициализирована. (Исключение из HRESULT: 0x8013131A). The error code is CORDBG_E_STATIC_VAR_NOT_AVAILABLE, or 0x8013131A.

    Может быть, дебаггер пытается разыменовать указатель

    Но если попытаться вывести в консоль значение Ptr, то будет 0:
    unsafe {
      void* x = null; // Можно выводить и Env.Ptr - будет тот же результат
      Console.WriteLine((nint)x); // 0
    }
    Ответ написан
    Комментировать
  • Как в архитектурах risc одинаковые виртуальные адреса разных контекстов задач различаются?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В risc вроде там куча csr регистров

    Вот на этом месте остановись. RISC -- это не конкретный набор инструкций и регистров, это принцип организации набора инструкций. RISC-процессоры все разные, возьми крнкретный и разбирайся с ним, не вали их все в одну кучу, не ставь на вопрос теги процессоров которые не имеют к нему отношения.

    на разных компиляторах одна си операция ассемблируется то в комбинацию lui + addi, то в комбинацию auipc +addi

    Ты указал ARM в тегах, но у ARM нет инструкций lui и auipc. Такие инструкции есть у RISC-V.
    Если ты посмотришь в The RISC-V Instruction Set Manual, раздел 2.4 Integer Computational Instructions, то увидишь, что опкод lui загружает константу собранную из 20 битов непосредственного значения из инструкции и 12 нулевых младших битов в целевой регистр, а auipc прибавляет такую же точно константу к PC и загружает в целевой регистр результат сложения, и в этом вся разница между ними.

    где какая используется не совсем понимаю.

    lui используется для генерации констант, которые не зависят от того, где расположен код, а auipc для генерации констант, которые двигаются вместе с кодом. Т.е. Если ты хочешь вызвать функцию, которая находится дальше чем ±2К от точки вызова, ты можешь сгенерировать её адрес инструкцией auipc, и полученный код будет работать одинаково, независимо от того, по какому адресу он будет размещён. А если тебе надо поместить в регистр константу, например 0x12345678, то ты можешь это сделать парой инструкций lui rd, 0x12345 ; addi rd, rd, 0x678 и значение константы будет всегда одинаковым, вне зависимости от того, где будет этот код.

    Каким образом одинаковые адреса различаются. Или они просто не могут быть одинаковыми(типа ос позаботиться)?

    Если есть MMU и он используется ОС, то есть и виртуальные адреса и они могут быть одинаковыми у разных процессов. Если MMU нет или он не используется, то ОС размещает все процессы в одном адресном пространстве, нет смысла говорить отдельно о виртуальных адресах, поскольку они равны физическим, адреса выделяемые ОС разным процессам могут быть как одинаковыми (например несколько процессов запущенных из одного исполняемого образа могут использовать один и тот же код и константные данные), так и разными (например изменяемые данные разные у всех процессов, а стеки разные у всех потоков).

    Как они в tlb обрабатываются, если вдруг они реально могут быть одинаковыми, и там нету ни каких дополнительных индексов процесса)

    Выбери конкретную процессорную архитектуру -- обсудим. у многих RISC-архитектур есть ASID, который идентифицирует адресное пространство и записывается вместе с виртуальным адресом в TLB. Но в любом случае ASID -- это просто оптимизация для повышения производительности, когда он отсутствует или переполняется ОС должна сбрасывать содержимое TLB при переключении адресного пространства.

    У ARM есть регистры TTBR с примерно той же функцией, что и cr3 в x86.
    У RISC-V есть CSR satp, содержащий ASID и базовый адрес корневого каталога страничных таблиц. Об этом можно прочитать в разделе 4.1.12 Supervisor Address Translation and Protection (satp) Register спецификации The RISC-V Instruction Set Manual Volume II: Privi....
    Ответ написан
    Комментировать
  • Как записать функцию в память, и вызвать по адресу c# небезопасный код?

    petermzg
    @petermzg
    Самый лучший программист
    Для этого нужно погрузиться в WinAPI.
    Вам следует сначала изучить флаги защиты страниц памяти, код может исполнятьтя только в странице памяти с флагом PAGE_EXECUTE.
    Потом нужно понимать в 32 или 64 битной среде выполняется код и какой calling convention нужен для функции, так как у 32 битной версии много типов передачи параметров cdecl, cdecl, fastcall, у 64 битной в основном fastcall.
    Ответ написан
    Комментировать
  • Зачем нужно выравнивание больше чем двойное машинное слово? Директива p2align 4 и более?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему нужно 512-356 байт нулями заполнять, почему нельзя продолжить дальше. Ведь следующая после 86*4 байт инструкция(или переменная) будет выровнена

    А вот еслы бы ты тупо взял и прочитал документацию на директиву .p2align, то у тебя таких вопросов не было бы. Потому что никто не заполняет 512-356 байт после. .p21lign выравнивает текущий адрес по заданной степени двойки. Обычно для этого есть аппаратные причины, например базовый регистр таблицы векторов прерываний может иметь 9 младших бит зафиксированных в 0. Или вот по границе страницы MMU выравнивают данные в ELF-файлах, чтобы можно было установить отдельно разрешения RX для кода и констант и RW для изменяемых данных.

    для получения элемента допустим table[index_nBit] можно применять операцию ИЛИ вместо сложения. Что быстрее. В этом ли дело

    Нет, не в этом.
    Ответ написан
    1 комментарий
  • Какой есть Алгоритм оптимизации перерасчета прочности соединений полигонов в системе при приложение силы?

    begemot_sun
    @begemot_sun
    Программист в душе.
    В общем случае для статической реализации - это система линейных уравнений с № неизвестными.
    Для динамической реализации - это система дифференциально-интегральных уравнений.
    Дальше копайте методы их решений.
    Ответ написан
    Комментировать
  • Какой есть Алгоритм оптимизации перерасчета прочности соединений полигонов в системе при приложение силы?

    Griboks
    @Griboks
    Ничего не понятно. Что такое 2d полигоны и балочные/нитевые/прямые/непрямые соединения, прямоугольники? Причём здесь дерево? Как алгоритм связан с количеством полигонов, если речь про расчёт соединений? Что именно рассчитывать, если соединения абсолютно нерастяжимые? Опишите, пожалуйста, задачу физически/математически.

    Если рассуждать абстрактно, то из точки приложения сила распространяется по дереву с затуханием, которое обусловлено коэффициентом сопротивления вращению абсолютно неупругой ветки относительно абсолютно неупругого ствола. Тогда можно найти минимально вращающегося родителя, затем рассчитать вращение потомков рекурсивно. Вращение потомка = собственное вращение + вращение родителя. Инерцией, натяжением, упругостью пренебрегаем. Родитель вращает потомков как жестко фиксированную систему материальных точек. Потомок вращает родителя как коэффициент сопротивления, т.е. ненмого вращается сам, немного вращает родителя.
    Ответ написан
    Комментировать
  • Какие части ПО могут быть общие у 2 операц. систем Wind-ы на 2 дисках разных? Лагает рабочий стол?

    @res2001
    Developer, ex-admin
    Возможно глюки какого-то из драйверов, может быть видео драйвера.
    Видимо, драйвер один и тот же используется в обеих виндах. Поэтому и ведет себя одинаково. Сам драйвер установлен в разные метса, но он один и тот же.
    Попробуйте обновить драйвер с сайта производителя. Или если уже стоит последняя версия - понизить версию.

    На счет загрузки ЦП - 10-20%% может быть не показатель. Если ядер много, а 10-20%% это средняя цифра по всем ядрам, то одно из ядер может быть загружена на 100%, а остальные по 1%. В менеджере задач включите отображение графика загрузки ЦП для всех ядрер.
    Ответ написан
    Комментировать
  • Какие части ПО могут быть общие у 2 операц. систем Wind-ы на 2 дисках разных? Лагает рабочий стол?

    @Drno
    Поставь вин10 ltsc
    Отключи автообновление драйверов виндой
    Отключи автообновление
    Установи драйвера с сайта производителя
    ручками
    Ответ написан
    3 комментария
  • Какие части ПО могут быть общие у 2 операц. систем Wind-ы на 2 дисках разных? Лагает рабочий стол?

    3r1k
    @3r1k
    the quieter you become, the more you hear
    рабочий стол начинает лагать. окна не перемешаются. списки под мюню ними обновляются с задержкой, скролы с задержкой, перемещение мышки с задержкой


    такое поведение характерно при переполнении буфера GPU.
    при таких условиях frame buffer нагружается на 100% и начинаются подобные лаги.
    Ответ написан
    5 комментариев
  • Почему StringBuilder при вызове метода ToString() копирует содержимое?


    Потом как правило объект StringBuilder находиться в методе, и сразу. умирает, то есть он вполне может использовать стек а не кучу

    Нет, не может, тк размер финальной строки заранее не известен, а если очень много памяти на стеке выделять, то его просто порвёт.


    Потом вообще почему любое new String (char[] ) копирует массив? почему не оборачивает

    Потому что string имеет контракт "никогда и ни при каких условиях содержимое строки не будет изменено". Если просто оборачивать, то этот контракт легко будет нарушить.

    А так да, можно и быстрее, если ты сможешь доказать, что ты никак не изменишь буфер, на котором основана строка после того, как можно будет использовать экземпляр string.

    Например как в случае со string.Create где ты можешь прокинуть лямбду, котороя сможет как угодно менять содержимое строящейся строки.
    string.Create выделяет память только один раз
    Ответ написан
    Комментировать
  • Какой смысл команды dup в JVM байт коде? И что за индексы локальных переменных?

    mayton2019
    @mayton2019 Куратор тега Java
    Bigdata Engineer
    Какой смысл команды dup в JVM байт коде?

    Жаль что ты не программировал на калькуляторе МК 60. Это целая эпоха.

    Значит есть разные пути к вычислению арифметики. Например если тебе надо возвести в квадрат число 5 на регистровой машине - то ты должен загрузить регистр R1 числом. Потом регистр R2. И потом найти такую команду умножения которая свяжет регистры R1 и R2 и перемножит и сохранит еще где-то результат. В силу современного зоопарка процессоров практически нереально создать такой абстрактный байткод который бы эффективно отображался на опкоды разных железяк. Поэтому решили забить на регистровую машину. И использовать стек как хранилище операндов для операций. Разумеется в JVM есть и аналоги регистров но с ними не выполняются операции. ЕМНИП. Если хошь что-то сложить или вызвать функцию - то положи на стек и там-же получи результат. И если вернуться к возведению числа 5 в квадрат это может быть так

    положить 5 на стек.
    дублировать
    вызвать функцию умножения


    На каком-нибудь языке Forth это было-бы тремя командами
    5 DUP * .
    Результат - на вершине стека.

    Это кратко записывается. Но это несет абсолютно ту-же смысловую нагрузку для арифметики.

    Почему их только 256 может быть?

    А чорт его знает. Так решили. Решили что 256 регистров это капец какой максимум для процедуры или функции. Послушай ради интереса видосы про процессор Эльбрус. Там тоже интересно с регистрами сделано.

    о есть на этапе генерации байт кода, сюда можно было после команды, просто адрес сразу впихнуть. И скорость выполнения должна же быть быстрее.

    Я думаю что твое предположение о том какой код соберет JIT не совсем верное.
    Вместо спора я предлагаю взять какой-то тестовый сценарий и подсмотреть какой
    будет собран код. Я знаю что скептики Java обычно после изучения вопроса глубже
    меняют свою точку зрения. Ну по крайней мере перестают считать Java
    "медленным покемоном". Java действительно была слоупоком во времена Jdk 1.1.
    Но щас это не так.

    Несколько лет назад я мерял производительность floating-point вычислений на приложении
    которое рендерит зеркальные шары. И разница между С++ и Java была не сильно большая.
    10 секунд на сях и 12 секунд на втором языке соотв. Хотя этот тест узкий и он просто
    показывает частный случай.
    Ответ написан
    4 комментария