Преамбула
Фирма, в которой я работаю, производит аппаратуру для нейрохирургов и нейрофизиологов, в основе которой лежит технология Deep Brain Stimulation. Если коротко, в живой мозг втыкается электрод, и нейрохирург может считывать из мозга сигнал или стимулировать клетки мозга разрядом тока. У технологии огромное будущее в деле лечения болезней (например, болезни Паркинсона, дистонии, эпилепсии) и в создании нейроинтерфейсов: нейропротезирование, в частности, восстановление зрения; аугментация мозга дополнительными устройствами, расширение возможностей мозга. Скажем, спецслужбы очень интересуются способом считывать и записывать информацию из зрительных и слуховых нервов, а также управлять движением животных, что позволит создать новый класс шпионов.
Для клинического применения в целях лечения тремора при болезни Паркинсона достаточно лишь нескольких внедряемых контактов (а некоторые нейрохирурги обходятся вообще одним). Но для исследователей, изучающих работу мозга, количество контактов имеет значение, и им нужно получать данные от как можно большего числа контактов одновременно и синхронно. Скажем, тысяча, или две тысячи внедрённых в мозг контактных площадок. Понятно, хотелось бы, чтобы и скорость была пристойной, — скажем, сорок тысяч замеров с каждого контакта в секунду. И чтоб разрешение было повыше, чтоб каждый замер был хотя бы в 32 бита, в формате float или Q. Получаем, что система производит порядка 320 мегабайт данных в секунду, так что всё это придётся обрабатывать.
Кроме считываемых непосредственно из мозга «чистых» данных, есть ещё данные отфильтрованные: результат применённых к замерам фильтров верхних и нижних частот. Используются фильтры высоких порядков, хотя бы четвёртого, реализованные в виде полиномов. Они применяются к каждому входящему замеру, увеличивая количество данных, о которых система должна заботиться, вчетверо, и поднимая количество генерируемых данных до 1,3 гигабайта в секунду. Но это уже не моя забота, потому что они генерируются из переданных мной данных после того, как я свою часть работы выполнил.
Результат всего этого счастья нужен в режиме реального времени и крайне важен. Пропускать нельзя ни одного замера, потому что основную работу по анализу данных исследователи выполняют после окончания эксперимента. Поэтому всё это богатство данных, помимо показа на экране, придётся записывать на жёсткий диск. Все 1,3 гигабайта данных в секунду. И потом читать в Matlab`е, NeuroExplorer`е или другой программе. Система, которая сохраняла 99,99999% данных, не прошла контроль качества и была забракована, потому что теряла до 13 тысяч замеров каждую секунду.
А вот теперь мы со всем этим попробуем взлететь.
Формулировка задачи
Имеется разработанная фирмой плата с контроллером FPGA, с одной стороны в которую воткнуты провода, идущие от мозга, (ну, на самом деле, от конвертеров, типа такого), а с другой есть выход PCIe. Этим выходом плата будет воткнута в порт PCIe на самом обычном, просто очень мощном, компьютере.
Мне предстояло создать драйвер, который получает данные потенциалов от этой нашей кастомной платы, обрабатывает на подключённой к тому же PCIe видеокарте (результат расчёта фильтров одного контакта не зависит от результатов другого; глупо не использовать для независимых расчётов процессор, который специально заточен на выполнение большого числа однотипных параллельных расчётов одновременно) и передаёт дальше в пользовательский интерфейс. И делать это надо очень-очень быстро, потому что новые пакеты с восемью замерами данных от каждого контакта приходят каждые 200 микросекунд. И, самое главное, сделать это надо под десятой Виндой, потому что нейрохирурги не знают и знать не хотят ничего, кроме Винды и Мака. Причём, судя по внешнему виду некоторых клиентов и адекватности высказываемых ими требований к программе, последнее слово предыдущего предложения можно писать с маленькой буквы.
Люди в теме уже сообразили, что речь идёт о hard realtime: гарантированный ответ на полученные данные в течение фиксированного времени, и неважно, что за дичь творится вокруг, без возможности задержаться или пропустить хотя бы один пакет. Эти же люди в теме уже покачали головой: творящаяся вокруг дичь — это Windows, hard realtime под Windows невозможен, Windows не операционная система реального времени. Более того, Windows не заточен под работу с квантами времени меньше миллисекунды, поэтому работа со скоростью «полный цикл обработки данных за 200 микросекунд» под Windows невозможна вдвойне.
Soft realtime отличается от hard realtime тем, что в soft иногда небольшие задержки всё-таки разрешены, при условии, что система от задержки очухается и успеет наверстать упущенное и разгрести данные, накопившиеся за время задержки, без потери производительности.
Существуют всякие расширения под Windows, которые позволяют частично имплементировать realtime. Например, операционные системы On Time, RTX64 от IntervalZero и прочие. Они сводятся к одной и той же идее: мы отбираем у Винды одно или несколько ядер и кусок памяти, делаем вид, что их в компьютере больше нет, и запускаем на них свою собственную операционку. После того, как этот монстр Франкенштейна раскочегарится и выйдет на рабочий режим, на компьютере будут работать одновременно две операционных системы: realtime и Windows. Между ними можно настроить общение. Это решение будет работать с двумя оговорками: во-первых, из-под Windows практически нет возможностей повлиять на то, что происходит внутри запущенной параллельно realtime ОС, (например, программы для неё надо компилировать при помощи проприетарной SDK; нельзя во время работы передать в неё свою собственную программу для обработки получаемых данных и запустить её), а во-вторых, стоимость этого решения, мягко говоря, неадекватна. Лицензия разработчика RTX64 стоит порядка 10 тысяч долларов, а за каждый экземпляр готового продукта, ушедшего клиенту (тому самому нейрохирургу), придётся заплатить ещё 500 долларов. Вдобавок к 600-долларовой лицензии на Винду, которую клиент тоже получит. Это выводит общую стоимость продукта из зоны конкурентоспособности и делает его финансово непривлекательным для потенциальных покупателей.
За десять тысяч долларов плюс неустановленное количество 500-долларовых лицензионных платежей я сам себе RTOS под Windows напишу, подумал я. И написал.
Применённые технические хитрости
-
Во-первых, нам нужно, чтобы как можно больше работы выполняла наша плата с FPGA на борту. Скажем, передачу данных лучше перевесить на неё: у неё DMA-контроллер точно ничем не будет занят, нет шансов, что, когда нам потребуется DMA-канал, Винда скажет нам в ответ «в очередь, линуксьи дети, в очередь!»
Как подключать FPGA к PCIe так, чтобы DMA писал данные, куда надо, это совсем-совсем отдельная тема, которая выходит за рамки данной статьи. Скажу только, что FPGA должен быть сконфигурирован как PCIe Endpoint, потому что компьютер остаётся Root Complex, — ему ведь ещё видеоадаптером управлять. При этом, раз DMA запускается платой, то и трансляция адресов должна выполняться на плате. И тут возникает вопрос: а куда плата будет писать? Изнутри Windows я могу работать только с виртуальными адресами. Даже если я выделю реальную память при помощи MmAllocateContiguousMemory, я получу только виртуальный адрес, достучаться до которого плата не сможет.
Так что совсем без решений Франкенштейна обойтись не удалось. Я резервирую кусок физической памяти на компьютере для использования только нашим устройством, выполнив в командной строке от Администратора команду следующего вида:
bcdedit /set removememory Х
(Х — сколько мегабайт зарезервировать)Таким образом, последние мегабайты скрыты от Windows, и обращаться к ним Винда не может. Помимо гарантии отсутствия столкновений на memory bus, таким образом решается ещё несколько проблем, в частности, отсутствует нужда в синхронизации доступа, что лишает меня необходимости использовать долгие и медленные семафоры и мьютексы. (Синхронизацию между записью данных в память и чтением можно осуществлять по времени: пусть плата пишет в пять буферов с разницей в 200 микросекунд; зная, что в нулевой буфер она писала в целое число миллисекунд, я буду читать буферы с отставанием на один: в целую миллисекунду — четвёртый, в миллисекунду и 200 микросекунд — нулевой, в миллисекунду и четыреста микросекунд — первый, и так далее. Как синхронизировать время на уровне микросекунд между двумя устройствами — задача, при наличии канала связи между ними, решаемая).
-
Драйвер, который будет читать данные из зарезервированной памяти, бежит строго на одном ядре. Для этого я меняю его привязку к процессору:
/* * The ID of the PCI driver CPU core. Starting from 0. */ static constexpr USHORT DRIVER_CPU_ID = 3; . . . . // Set the thread to run on specific processor KAFFINITY affinity = 1ULL << (DRIVER_CPU_ID); KeSetSystemAffinityThread(affinity);
— и поднимаю его приоритет, но не до высшего, а до того, который чуть ниже. На самом высшем приоритете некоторые системные функции не работают, и критические системные задачи, которые бегут на таком же приоритете, не будут выполняться:
// Set the thread priority to the highest available -1 // Тhe "-1" is because running for a long time in HIGH_PRIORITY // "starves" important system tasks which run in HIGH_PRIORTY KeSetPriorityThread(PsGetCurrentThread(), HIGH_PRIORITY - 1);
-
Но этого недостаточно. Нужно не только чтобы этот процесс бежал на одном ядре, но и чтобы никакой другой процесс на этом ядре не бежал. Для этого я поднимаю приоритет прерываний, которые могут прервать выполнение моего процесса (
KIRQL
), до максимального (DISPATCH_LEVEL
):KIRQL oldIrql; KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
Однако процесс не может всё время бежать с запретом на любые прерывания, Винда за этим строго следит и может наглеца прибить. Поэтому периодически я понижаю приоритет прерываний, которым разрешаю свой процесс, гхм, прерывать. Чисто формально, но всё-таки:
// It's important that we don't stay at DISPATCH_LEVEL for too long // so we record the last tick we were at passive, and every once in // a while lower the KIRQL static constexpr ULONG64 MS_ALLOWED = 50; LARGE_INTEGER freq{}; LONGLONG lastPassiveTick = 0; . . . . . . KeQueryPerformanceCounter(&freq); timePassed = ((KeQueryPerformanceCounter(nullptr).QuadPart - lastPassiveTick) * 1000ULL) / freq.QuadPart; if (timePassed >= MS_ALLOWED) { yieldProcessor(); lastTickAtPassive = KeQueryPerformanceCounter(nullptr).QuadPart; } /* Yield Processor means lowering to PASSIVE_LEVEL and then raising back * to DISPATCH_LEVEL. It allows other important tasks to run in between, * if they are fast enough. */ void yieldProcessor() { KIRQL oldIrql; KeLowerIrql(PASSIVE_LEVEL); KeRaiseIrql(DISPATCH_LEVEL, &oldIrql); }
-
А теперь самое весёлое.
При инициализации драйвера я прохожу по всем имеющимся в операционной системе процессам и меняю их привязку к процессору:
namespace accelerator {
class IAccelerator {
public:
explicit IAccelerator() = default;
virtual void revert() = 0;
virtual void accelerate() = 0;
virtual ~IAccelerator() = default;
};
}
namespace accelerator {
const std::vector<std::wstring> DEFAULT_BLACKLIST_PROCESSES = {
L"system",
L"system.exe",
L"winlogon.exe"
};
class AffinitySetter : public IAccelerator {
public:
/**
* Sets the processor affinity of all processes.
*
* Affinity is reset upon reseting the computer.
*
* @param activeCpuIdentifiers The cpu identifiers which should NOT be used by any process.
* @param blacklistProcesses A list of processes that should not be altered.
*
*/
explicit AffinitySetter(std::vector<uint8_t> activeCpuIdentifiers,
std::vector<std::wstring> blacklistProcesses = DEFAULT_BLACKLIST_PROCESSES);
virtual void revert();
virtual void accelerate();
virtual ~AffinitySetter() = default;
private:
ULONG_PTR getAffinityMaskWithoutBlackList(ULONG_PTR maskLimit);
std::vector<uint8_t> m_activeCpuIdentifiers;
std::vector<std::wstring> m_blacklistProcesses;
};
}
. . . . . . .
std::vector<std::unique_ptr<accelerator::IAccelerator>> accelerators;
auto affinitySetter = std::make_unique<accelerator::AffinitySetter>(
std::vector<uint8_t>({ DRIVER_CPU_ID }));
accelerators.push_back(std::move(affinitySetter));
for (auto& accelerator : accelerators) {
accelerator->accelerate();
}
-
Но и это ещё не всё. Мало позаботиться о тех процессах, которые уже есть, надо ещё позаботиться о тех, которые пользователь создаcт в будущем. Для этого я регистрирую два системных коллбэка, на создание процесса и на создание потока; они вызываются для каждого нового процесса и потока, и я меняю их привязку к процессору:
/* * We want to keep this core to ourself, so register a callback for each * process and thread created. At this callback we change their affinity * (the core they can run on) to be different from our core */ if (!NT_SUCCESS(PsSetCreateProcessNotifyRoutine(newProcessCreated, FALSE))) { DEBUG_TRACE("PsCreateProcessNotifyRoutine failed"); COMPLETE_IRP(Irp, STATUS_UNSUCCESSFUL); } FINALLY([&guardActivator]() { if (guardActivator) { PsSetCreateProcessNotifyRoutine(newProcessCreated, TRUE); } }); if (!NT_SUCCESS(PsSetCreateThreadNotifyRoutine(newThreadCreated))) { DEBUG_TRACE("PsCreateProcessNotifyRoutine failed"); COMPLETE_IRP(Irp, STATUS_UNSUCCESSFUL); } FINALLY([&guardActivator]() { if (guardActivator) { PsRemoveCreateThreadNotifyRoutine(newThreadCreated); } }); . . . . . . void newProcessCreated( HANDLE ParentId, HANDLE ProcessId, BOOLEAN Create ) { UNREFERENCED_PARAMETER(ParentId); if (Create) { KAFFINITY affinity = ~((1ULL << (DRIVER_CPU_ID))); KAFFINITY maximumAffinity = KeQueryActiveProcessors(); affinity &= maximumAffinity; // Get process handle by id HANDLE processHandle; OBJECT_ATTRIBUTES objectAttributes{ 0 }; InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); CLIENT_ID clientid{ 0 }; clientid.UniqueProcess = ProcessId; auto status = ZwOpenProcess(&processHandle, GENERIC_ALL, &objectAttributes, &clientid); if (!NT_SUCCESS(status)) { DEBUG_TRACE("ZwOpenProcess failed getting process for pid %d with status %d", ProcessId, status); return; } FINALLY([&processHandle]() { ZwClose(processHandle); }); // Set the process affinity by handle DEBUG_TRACE("Will set process affinity: %d for process: %d", affinity, ProcessId); if (affinity) { status = ZwSetInformationProcess(processHandle, ProcessAffinityMask, &affinity, sizeof(affinity)); if (!NT_SUCCESS(status)) { DEBUG_TRACE("ZwSetInformationProcess failed getting process affinity for pid %d with status %d", ProcessId, status); return; } } } } void newThreadCreated( HANDLE ProcessId, HANDLE ThreadId, BOOLEAN Create ) { if (Create) { // Thread affinity should eventually be all cpus except our own. KAFFINITY affinity = ~((1ULL << (DRIVER_CPU_ID))); KAFFINITY maximumAffinity = KeQueryActiveProcessors(); affinity &= maximumAffinity; // Get process handle by id HANDLE processHandle; OBJECT_ATTRIBUTES objectAttributes{ 0 }; InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); CLIENT_ID clientid{ 0 }; clientid.UniqueProcess = ProcessId; auto status = ZwOpenProcess(&processHandle, GENERIC_READ, &objectAttributes, &clientid); if (!NT_SUCCESS(status)) { DEBUG_TRACE("ZwOpenProcess failed getting process for pid %d with status %d", ProcessId, status); return; } FINALLY([&processHandle]() { ZwClose(processHandle); }); // Get the process affinity by handle PROCESS_BASIC_INFORMATION processInformation; ULONG returnLength; status = ZwQueryInformationProcess(processHandle, ProcessBasicInformation, &processInformation, sizeof(processInformation), &returnLength); if (!NT_SUCCESS(status)) { DEBUG_TRACE("ZwQueryInformationProcess failed getting process for pid %d with status %d", ProcessId, status); return; } // Reduce affinity to by subset of process affinity &= processInformation.AffinityMask; // Get thread handle by id HANDLE threadHandle; objectAttributes = { 0 }; InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); clientid = { 0 }; clientid.UniqueThread = ThreadId; status = ZwOpenThread(&threadHandle, GENERIC_ALL, &objectAttributes, &clientid); if (!NT_SUCCESS(status)) { DEBUG_TRACE("ZwOpenThread failed getting thread for tid %d with status %d", ProcessId, status); return; } FINALLY([&threadHandle]() { ZwClose(threadHandle); }); // Set the thread affinity by handle DEBUG_TRACE("Will set thread affinity: %d for thread: %d", affinity, ThreadId); if (affinity) { status = ZwSetInformationThread(threadHandle, ThreadAffinityMask, &affinity, sizeof(affinity)); if (!NT_SUCCESS(status)) { DEBUG_TRACE("ZwSetInformationThread failed getting thread affinity for tid %d with status %d", ProcessId, status); return; } } } }
Надо только не забыть убрать эти коллбэки при окончании работы.
Заключение
По факту, я реализовал систему, работающую в реальном времени, внутри Windows. Техника, в общем-то, такая же, как у коммерческих решений типа вышеупомянутой On Time: я забираю под свои цели ядро и часть памяти и не позволяю Windows добираться до них и мешать мне. Но есть и отличие: моё решение работает внутри Windows, в пространстве ядра, и позволяет пользоваться всеми преимуществами операционной системы. Я не ограничен в общении с остальными программами операционной системы и могу использовать весь набор средств для межпроцессного взаимодействия. Более того, я могу вернуть занятое драйвером ядро обратно Windows в любой момент, достаточно только убрать мои коллбэки и пройтись по процессам, исправляя их привязки.
Время обработки одного пакета данных при таких условиях не превышает 155 микросекунд, включая добавление заголовков к каждому пакету данных. Затем данные передаются из зарезервированной памяти в программу обработки, которая уже заботится о передаче данных в GPU, занимается показом всего этого богатства на экране и сохранением на жёсткий диск. Время передачи данных из платы в память компьютера здесь не учитывается, потому что я начинаю работать только после того, как данные окажутся в памяти.
Комментарии (120)
n2dt4qd2wg9b
18.02.2022 14:17А что если писать на кучку SSD сразу на FPGA? А потом лениво тащить в любую систему?
Alex_Hitech Автор
18.02.2022 14:22+1Задержка будет большой. Там одно из условий — задержка между генерацией в мозге сигнала определённого вида и отправкой стимуляции в мозг в одну миллисекунду. Определённый вид можно узнать только после фильтра высоких частот, то есть нужно получить данные, пропустить их через фильтр, наложить шаблон, получить соответствие и принять решение о стимуляции за миллисекунду.
Сейчас, в предыдущей версии, где фильтр выполняется на отдельном DSP, задержка 1.2 миллисекунды, и это абсолютный максимум, если сделаю хуже — продукт не выпустят.
OvO
18.02.2022 14:36+1Под Windows такого еще не приходилось видеть. Было бы интересно взглянуть статистику отклонений времени выполнения кода на хотя бы на 48-часовом тесте при нагрузки I/O основной системы. На Linux, в зависимости от оборудования, ~30us jitter вполне реально получить, как в Windows c этим?
А вариант с запуском Windows в виртуальной машине рассматривали?
Alex_Hitech Автор
18.02.2022 14:54+2Пока что максимальный тест, который я гонял, длился только 7 часов. Я ж только взялся за работу, это первые судороги моего монстра Франкенштейна :-)
Windows в виртуальной машине рассматривался, но был отметён сразу, как только я сказал, что придётся запускать на одном компе две операционки и использовать программу, которая транслирует вызовы из одной в другую. Если запускать внутренний Windows на полный экран сразу при загрузке компьютера, то кто и как будет заботиться об обновлениях внешнего Linux? Он, вообще-то, почти напрямую к мозгам подключён, если оставить его без обновлений, FDA взвоет. Какие-то автоматические решения использовать? - Я не спец в безопасности Linux`ов, боюсь в такие вещи лезть... А если не грузить виртуальную машину сразу, клиенты увидят непривычный интерфейс, впадут в кому и откажутся работать. Мы уже тестировали систему с Linux`ом на студентах, они пугаются. И это закалённые пьянками студенты-медики! Каково будет взрослым именитым докторам?!.. :-)
И, кажется, Matlab, который они будут запускать из-под виртуальной Винды, чтобы обрабатывать результаты расчётов, может работать медленнее, чем в "настоящей" системе.OvO
18.02.2022 15:20Если речь идет только об одном драйвере, без среды, то linux плохое решение. Лучше взять гипервизор и запустить опрос для fpga на одном ядре, а остальное под Windows отдать и получится красиво.
Я сейчас как раз с подобным работаю, но для arm, для Intel совершенно точно есть решение VxWorks+Windows и что-то еще можно найти.
13werwolf13
18.02.2022 15:47Я сейчас как раз с подобным работаю, но для arm.
а можно чуть подробнее? там в VM выньда тоже будет arm, или эмуляция x86? просто у меня сложилось впечатление что arm версия винды максимально безполезна, под неё софта почти нет (даже родного мелкомягкого офиса не подвезли)..
и какие задачи этим решаются?
OvO
18.02.2022 15:57Подобным, в смысле RTOS на cortex-a запускает Linux на других ядрах, baremetal на cortex-r, а сама занимается обработкой высокоприоритетных задач, выдавая в Linux результат для обработки и отображения. Linux нужна только для bash, python, библиотек и среды, но возможно мы ее тоже выкинем. Извините, никакого Windows.
13werwolf13
18.02.2022 16:04+2а, ну вот теперь эту звучит логично и правильно.. там где нужна стабильность и хоть какие-то гарантии выполнения винде просто не место.
Alex_Hitech Автор
18.02.2022 17:27+6Ну почему же так сразу... У меня винда работала в качестве контроллера балконной двери. Я системником дверь подпирал, чтоб не закрывалась. Работала стабильно и без нареканий :-)
kekekeks
18.02.2022 15:52то кто и как будет заботиться об обновлениях внешнего Linux?
Из под Windows по SSH к нему управляющим софтом стучаться или через VNC показывать в окошке.
Всю физическую периферию включая встроенное видео, сетевой адаптер и USB-контроллер при этом пробросить в Windows чтобы люди не пугались.
Alex_Hitech Автор
18.02.2022 17:26+1Это надо будет сисадмину больницы объяснять. Причём не мне, я разработчик, а продажникам и техподдержке. Ни те, ни другие Линукса в глаза не видели, и не горят желанием смотреть... И я их прекрасно понимаю.
kekekeks
18.02.2022 23:16Так поставляйте программно-аппаратный комплекс целиком. Всё равно ведь в системник видеокарту и PCI-плату с FPGA втыкаете.
Alex_Hitech Автор
18.02.2022 23:41Нет, в одной из конфигураций мы продаём только плату, а покупатель собирает комп сам.
Tarakanator
21.02.2022 13:11Ну самое простое решение пусть линуск проверяешь ключ (например флешку с определённым файлом). Если он присуствует-винда НЕ запускается.
icCE
18.02.2022 14:54+1Осталось еще для нормального RT использовать процессор , который это может. Я так понимаю тут используется x86 и своя обвязка. x86 RT по сути закончился на 80486 машинах.
А так надо убирать smm , me , psp и прочие плюшки от intel и от amd, которые они там продвигают.
P.S. По крайне мере я не увидел , на чем это реально работает и выводы сделан косвенные по фразе 10 винда
Alex_Hitech Автор
18.02.2022 15:26Реально там 64-битный Intel i7-9700 TE и 16 гигов памяти (из которых я кусок отрезал под свои игрища).
lorc
18.02.2022 15:55Ну совсем в диких задачах realtime уже и MMU начинает мешать (время трансляции адреса потенциально бесконечно), и SMP, как правильно заметили - чужое ядро может сделать lock на определенный адрес и привет.
Не зря у того же ARM есть Cortex M, а есть Cortex R для совсем хардкорного realtime.Alex_Hitech Автор
18.02.2022 17:24Это одна из причин, почему я отрезаю память и лезу в неё по захардкоженному адресу.
vsb
18.02.2022 15:52А что конкретно мешает использовать современный x86 процессор в роли эдакого очень мощного микроконтроллера? Без всякой ОС, загрузились с UEFI, инициализировали оборудование и пошли молотить числа.
Alex_Hitech Автор
18.02.2022 17:23Да, кстати, я такое делал. Правда, x86 в таких целях хуже, чем PowerPC G3, но, возможно, это субъективщина: с PPC я работал больше и, естественно, знаю их лучше, поэтому они мне кажутся удобнее.
Mozhaiskiy
18.02.2022 15:51А рассматривали ли вариант с Mac в качестве основной платформы? Всё-таки полноценная BSD внутри, никаких платных лицензий на OS, возможность сделать своё расширение ядра, компактные размеры (если macMini), на новых M1-системах очень приличная производительность графических ядер, стабильность, наличие большого числа клиентского софта, всякие скоростные SSD сразу из коробки.
Alex_Hitech Автор
18.02.2022 16:13+1Да, Mac рассматривался в качестве основной платформы. Но когда я озвучил, сколько будет стоить оснащение отдела разработки новыми компьютерами, идею отложили до лучших времён :-(
Mozhaiskiy
18.02.2022 17:35+1Что, кстати, довольно странно. Цена условного mini или air не столь высока (порядка 100К рублей), а для задач разработки их пока хватает с головой на внешнем мониторе, вы же не 3D там рендерите. А в качестве клиентского устройства, разница вообще отсутствует: качественное PC-железо + 40-50 тысяч за Win-лицензию дают ту же сотку. Зато у вас отсутствуют типичные Win-проблемы с их обновлениями и снятием с поддержки + получаете полноценную BSD систему с высокой защитой от дурака и левого вредоносного софта.
Alex_Hitech Автор
18.02.2022 19:15+1Ну, так то Mini. А я затребовал для разработчиков Pro в ха-а-арошей такой конфигурации. Потому что если у нас одна секунда данных весит гигабайт, а на час нужно около 4 терабайт, то, чтобы сохранить данные с одного ночного прогона (а это обязательный элемент тестирования), нужно иметь хотя бы 32 терабайта свободного места на локально подключённых дисках. То есть нужен ОЧЕНЬ большой системник, чтобы напихать в него много дисков и собрать из них Raid. Из больших системников у Apple только Pro и остался. Ну, а раз уж я раскатал губу на Pro, то не улучшить слегка конфигурацию будет просто глупо.
Mozhaiskiy
18.02.2022 20:43А в чём была проблема подключить внешнее хранилище по USB3/Thunderbolt? Его цена что для PC, что для Mac была бы абсолютно одинаковая. Разумеется, если вы для сравнительно небольших вычислительных задач запросили у руководства Pro ценой в миллион (предназначенный монтировать видео в 8K для кинокомпаний), только потому, что у него "большой корпус" вас завернули с таким бюджетом.
Но какое отношение это имеет к Mac, как к платформе? Давайте будем честны, проблема не в цене Mac, а в том, что вы запросили бизнес-джет с джакузи для задач аэрофотосъёмки. И имхо, абсолютно зря, потмоу что за те же деньги вы могли бы получить мощную холодную *nix систему с отличным железом без проблем с клиентами вообще.Alex_Hitech Автор
18.02.2022 20:48Никакого внешнего хранилища в системе быть не должно, ограничение сверху. Только внутренние ЖД. Ну и да, я хотел Pro :)
Abo73
18.02.2022 16:09А где в этой системе присутствует гальваническая изоляция мозга от цепей ПК? ПК же ведь прямо в сеть включен? Или от аккумуляторов питается?
Alex_Hitech Автор
18.02.2022 16:12+1ПК включён прямо в сеть, но FPGA запитана отдельно, через собственный источник питания, и изолирована от питания компьютера. Компьютер до мозгов не добьёт, если только не будет эпического пробоя, при котором уже неважно, что и как запитано.
В предыдущей версии FPGA находился в отдельном вынесенном устройстве в корпусе вместе с DSP и тоже был запитан через свой собственный источник питания.
Abo73
18.02.2022 16:39О питании понятно. А с помощью каких технологий удается изолировать на 4кВ гигабитный поток данных? Я тоже конструирую по работе похожее, но не подобное - обычные энцефалографы и миографы, у них поток данных в 60Мбит/с убирается и время реакции не так критично.
pvvv
18.02.2022 17:20оптический езернет, хотя и для медного есть трансформаторы и на более высокие напряжения, например https://pro-tek5.com/gigabit-ethernet-isolators/
Abo73
18.02.2022 17:32Спасибо. Учту.
А по архитектуре, я бы, основываясь на собственном опыте, не стал с виндой связываться на таких задачах. Потенциальный ущерб от сбоя ПО чрезвычайно высок, на мой взгляд.
pvvv
18.02.2022 17:03+2может кто подскажет, а как "добраться" до отрезанных bceditом процессорных ядер и запустить на них что-нибудь baremetalьное параллельно с работающей виндой?
Alex_Hitech Автор
18.02.2022 17:30Тут я пас. Но смотреть надо в сторону UEFI, потому что из-под Винды доступа к ним уже не будет, — значит, запускать надо до того, как Винда начнёт грузиться. А это примерно UEFI и есть.
Alex_ME
18.02.2022 17:50+1В задачах реального времени таки часто применяют Windows либо франкенштейнов на Windows. Насколько знаю, у KUKA (роботы-манипуляторы) свой.
Вроде как сейчас модно запускать гипервизор, в котором крутится несколько ОС, например, реалтайм-ОС и не реалтайм ОС (включая Windows) в качестве интерфейса.
Я не до конца знаю специфику Вашей предметной области, но если реалтайм-цикл (прием, запись, фильтрация, стимуляция) целиком работает без windows-специфики, то его можно делегировать на RT-ос (даже Linux), а интерфейс/постобработку оставить на винде.
Не вы первые, я думаю, вопросы, как реализовать обновления и сокрытие интерфейса, в промышленности реализованы.
В Intel занимается реалтаймом на линуксе (и немного на винде), в.т.ч. там есть какие-то наработки по гипервизорам. Из интересного: еще возможность оптимизировать передачу данных через Root Complex в разных направлениях (напр. PCIe<->memory) для приоритетного траффика с точки зрения уменьшения задержек.
Если интересно - напшите ЛС, сведу вас с командой, которая этим занимается.
XenRE
18.02.2022 19:52Возможно я ошибаюсь, но описанное в статье очень похоже на забор из костылей, выстроенный вокруг непродуманной архитектуры изделия. Если же у автора и имелась реальная необходимость в создании такого франкенштейна, то она не показана. В любом случае, стоит снабдить статью предупреждением вида «Описанное является грязным хаком, не используйте в своих проектах если не уверены в том, что делаете и к каким последствиям это может привести». Кривых драйверов и без этого достаточно.
Несколько вопросов по существу:Поэтому всё это богатство данных, помимо показа на экране, придётся записывать на жёсткий диск. Все 1,3 гигабайта данных в секунду. И потом читать в Matlab`е, NeuroExplorer`е или другой программе.
То есть по факту реалтайм не нужен, достаточно регистрировать данные без потерь. Например сложить в большой буфер и выгребать 10-20 раз в секунду.Они применяются к каждому входящему замеру, увеличивая количество данных, о которых система должна заботиться, вчетверо, и поднимая количество генерируемых данных до 1,3 гигабайта в секунду.
Если эти данные вычисляются из измерений, зачем это делать в реалтайме? Почему не сделать на постобработке?полный цикл обработки данных за 200 микросекунд
5кгц, не так и много, приходилось обрабатывать на порядок большую частоту прерываний без особых проблемм и извратов.Даже если я выделю реальную память при помощи MmAllocateContiguousMemory, я получу только виртуальный адрес, достучаться до которого плата не сможет.
Странное утверждение, а как же другие то делают? Про MmGetPhysicalAddress Вы не в курсе?Однако процесс не может всё время бежать с запретом на любые прерывания, Винда за этим строго следит и может наглеца прибить.
А Ваша плата что, вообще прерываний не генерирует? Данные выгребаются опросом регистров в цикле? Попахивает хреновой архитектурой.Alex_Hitech Автор
18.02.2022 20:15То есть по факту реалтайм не нужен, достаточно регистрировать данные без потерь.
Я несколько раз явно касался этого вопроса в комментариях. Нет, реалтайм нужен, потому что по регистрируемым данным может приниматься решение о стимуляции. Там ещё и ограничение latency в 1 миллисекунду между генерацией сигнала в мозге и началом ответной стимуляции. Без реалтайма никак. А решение принимается не по raw data, а по filtered data. Конкретно — по данным фильтра высоких частот. Поэтому фильтрацию придётся выполнять прямо внутри этого реалтайма.
Про MmGetPhysicalAddress Вы не в курсе?
Вот честно — нет. :) Я вообще не виндузятник, я программист DSP. Это мой первый код для Винды за очень-очень много лет, чуть ли не с окончания обучения.
5кгц, не так и много
40 килогерц, но данные, удобства ради, приходят сгруппированными в пакеты по 8 замеров.
А Ваша плата что, вообще прерываний не генерирует?
Конечно, нет!!! Прерывания — это зло. Вся архитектура решения построена так, чтобы в нём не было ни единого прерывания, только polling. Мы делали замеры, и в среднем на обработке прерывания теряется больше времени, чем на опросах.
XenRE
18.02.2022 21:42Нет, реалтайм нужен, потому что по регистрируемым данным может приниматься решение о стимуляции.
А это решение принимается в том же драйвере что и опрос? Каким образом оно настраивается? Что делать если надо изменить критерии — драйвер переписать? Что будете делать если (когда) логика принятия решения не влезет по времени в 1 поток?
А регистрация и отображение как делается? Данные же нужно отдать на user level, или по крайней мере другому драйверу.Прерывания — это зло
Которое генерит много разных устройств, например видеокарта или контроллер SATA. И DISPATCH_LEVEL не защищает от аппаратных прерываний.Alex_Hitech Автор
18.02.2022 23:40А это решение принимается в том же драйвере что и опрос?
И да, и нет. В одном из путей принятия решения решение о стимуляции принимается прямо внутри драйвера, для чего прямо в драйвере есть функционал фильтрации, и драйвер принимает от управляющей программы параметры (через общую память): какой канал фильтровать с какой частотой среза и при каком значении начинать стимуляцию с предопределёнными параметрами. В другом пути сигнал о начале стимуляции приходит от управляющей программы, которая, в свою очередь, получает его либо от исследователя через нажатие кнопки (либо в UI, либо физической, на пульте дистанционного управления), либо программно, от пользовательского скрипта.
Но требование latency до одной миллисекунды не включает в себя время, которое затрачивает на работу пользовательский скрипт. Если пользователь сделает там бесконечный цикл до принятия решения, это не проблема.
Что будете делать если (когда) логика принятия решения не влезет по времени в 1 поток?
У нас очень сильно многопоточная система. Приём и передача данных — это уже два разных потока, и бегут они на двух разных ядрах, а уж в интерфейсе их вообще штук двадцать.
И DISPATCH_LEVEL не защищает от аппаратных прерываний.
Да, кое с чем придётся смириться. Но смириться с неизбежным злом и способствовать ему — это разные вещи. У нас в программе прерываний нет.
meta_xil
21.02.2022 11:07Я очень надеюсь, что эту дичь закроют на этапе сертификации. Использовать абсолютно непригодное решенеие в системе которая может реально нанести вред пациенту, это уже за гранью. Тем более что вред может быть отложенным, неявным и так далее.
Никто и никогда не даст гарантии что ваше ядро не пересечется по кэшам/MMU с остальными. Есть еще слабая такая надежда - вырезать полностью CPU socket, со всеми ядрами, доступом к локальной памяти и, в случае с AMD, локальным PCIe. Но вот когда проснется ME/PSP и решит что пора бы занятся чем то более интересным чем людей лечить не скажет никто.
Думаю что никто не станет утверждать что современная медицина хотя бы в общих чертах представляет себе процесс мышления. Не на уровне - сюда электрод и вот у пациента нога дернулась. И последствия сбоя timeline стимуляции наверняка предсказать невозможно. Те люди которые делали предыдущую систему наверняка о чем то таком задумывались.
Hard RT он на то и RT что не бывает второй свежести. Либо от начала до конца процесса должно быть X инструкций всегда, либо это уже soft RT а там можное еще memory allocations добавить и придумать еще какое нибудь звучное название.
В вашем случае, если ваши фильтры использующеся в принятии решений, по какой то причине не лезут в FPGA (что само по себе странно), то можете посмотреть в сторону скажем семейства Nvidia Jetson. Там и акселератор есть и ARM ядра и PCI-E. Не RT траффик можно вообще гнать через USB3.
Ну или Xilinx ultrascale+ mpsoc, FPGA + matlab пишите фильры, есть ядра ARM R5, есть А53, есть PCI-E, как базовый, так и IP.
mvv-rus
19.02.2022 03:29+2Возможно я ошибаюсь, но описанное в статье очень похоже на забор из костылей, выстроенный вокруг непродуманной архитектуры изделия.
Тем не менее, это решение имеет то преимущество, что оно таки работает.
Однако, я хоть и далеко не специалист по архитектуре ядра Windows, но некоторое (очень некоторое, всего лишь на уровне многократного прочтения книги «Windows Internals» самых разных изданий) представление о ней имею, и в этом свете смотреть на это решение мне реально страшно. Я бы лично такое писать не взялся, так что автору, раз он смог — честь и хвала. Только вот, я бы добавил в статью ещё дисклеймер типа «не пытайтесь повторить это дома» — но это уже чисто личное мнение.Странное утверждение, а как же другие то делают? Про MmGetPhysicalAddress Вы не в курсе?
Может, оно и лучше — быть не в курсе? Ибо в документации по MmGetPhysicalAddress сказано:Do not use this routine to obtain physical addresses for use with DMA operations. For information about the proper techniques for performing DMA operations, see Adapter Objects and DMA.
(причину, почему так написано в документациии, врать не буду, не знаю).
А по ссылке из цитаты — весьма немаленький кусок про то, как надо писать драйверы устройств DMA под Windows по фэн-шую. IMHO разбираться в этом — не быстро (предполагаю, ибо сам не пробовал), а найти и нанять человека, который уже разобрался — не дешево, и опять же — не быстро.
Может, оно так даже и лучше, как автор сделал — максимально независимо от Windows: забрать себе кусок памяти, ядро процессора, и не сильно париться по поводу того, что там в остальной системе происходит?Alex_Hitech Автор
19.02.2022 05:24+2так что автору, раз он смог — честь и хвала.
Тут как в том анекдоте: «Ша, уважаемый, ша. Вы знаете, что это за алмаз и сколько он стоит. Я знаю, что это за алмаз и сколько он стоит. А Моня не знает, и он-таки сделает». Я просто не знал, во что влезаю. Знал бы — подумал бы дважды
и всё равно бы не полез.
XenRE
20.02.2022 22:03забрать себе кусок памяти
К этому кстати тоже есть вопросы, у автора:bcdedit /set removememory
А как потом найти отпиленный регион в адресном пространстве? Таки уверены что он ни с чем не перехлестнется?Мы делали замеры, и в среднем на обработке прерывания теряется больше времени, чем на опросах.
Если не секрет, сколько проходит от момента генерации прерывания до входа в обработчик (средне/макс)?Alex_Hitech Автор
21.02.2022 00:34+1А как потом найти отпиленный регион в адресном пространстве?
Через список ресурсов железа в registry. Да, он ни с чем не перехлестнётся, потому что находится за пределами доступной для Винды памяти. (Так адрес, в общем-то, и вычисляется, — берётся последний доступный Винде кусок памяти и к его адресу прибавляется его размер).
Если не секрет, сколько проходит от момента генерации прерывания до входа в обработчик (средне/макс)?
На нашем оборудовании 9-15 микросекунд.
buldo
19.02.2022 08:34А в данном решении используется dma или rdma?
То есть мне кажется логичнее в описанной ситуации писать из fgpa сразу в память GPU и оттуда дальше куда-нибудь тем же rdma, например в сетевуху.
P.S. выше только моё предположение. У нас в универе хотели что-то такое сделать - melanox сетевуха + пачка видюх + Intel edison. Поэтому и подумал о таком варианте.
akaAzazello
19.02.2022 17:58Я возможно, что-то упустил, но у меня никак не складываются цифры - с одной стороны, это потенциальный риск для здоровья человека (и страховые выплаты порядка 1 млн $), с другой суммы порядка 10к$ - это дорого (как за готовое решение, так и за девелоперские маки), использование дешёвого Intel Core со специально отключенным ECC для памяти вместо Xeon/любого AMD и т.д.
Ну и технический вопрос - как вы учитываете, что Windows может перезагрузить GPU драйвер в любой момент?
Alex_Hitech Автор
20.02.2022 02:34Это решение (пока) не для клиник и не для людей, а для исследователей и для животных, так что риски для здоровья нас волнуют мало. И сумма будет не 10к$, стоимость продукта начинается от 25к$ и, в максимальной конфигурации, хорошо превышает 250к$. При этом DSP пошёл под нож из-за подорожания на 60, кажется, долларов. Потому что в себестоимости буквально каждый цент на счету; никто не будет готовить и выпускать продукт, не обеспечив себе хотя бы 600-800% чистой прибыли.
Ну и технический вопрос - как вы учитываете, что Windows может перезагрузить GPU драйвер в любой момент?
Никак не учитываем. Просто пропишем это в мануале, и пусть у юзера голова болит.
emusic
20.02.2022 13:09+1"Драйвер бежит", "задачи бегут" - это что за ужас? Лексикон малограмотных пионеров, не осиливших адекватные эквиваленты англоязычной терминологии, овладевает и разработчиками ядерного уровня?
Как-то очень печально такое видеть.
DjPhoeniX
20.02.2022 21:45Вы удивитесь, но очень многие употребляют этот термин, произошедший из дословного перевода с английского “running”. Сначала сам напрягался, потом привык.
emusic
20.02.2022 23:36+1Так я знаю, откуда он взялся, и что его употребляют всякие недоучки, не осилившие родного языка. Но у автора статьи речь вроде адекватная, откуда ж туда затесался этот словесный хлам?
Alex_Hitech Автор
21.02.2022 00:35Ну так я не из России, русский — далеко не основной мой язык, русскоязычные термины я не знаю и знать, в общем-то, не обязан. Перевёл, уж как сумел.
DjPhoeniX
21.02.2022 00:42Всё же открыл профиль. Израиль. Да, те из моих знакомых, кто выражается аналогичными терминами, тоже в основном оттуда. Наверное, это локальная особенность…
Не за и не против такого перевода. Все поняли суть, хоть и не «устоявшееся» и кто-то словит секундный loading при первом прочтении. Я вот даже внимания не обратил…
Asam1982
21.02.2022 00:35+2Как интересно! Лет 20 назад решал похожую задачу, но в меньших масштабах. Надо было в режиме реального времени управлять платой ЦАП/АЦП со временем порядка 10 мкс. И конечно все умели пользоваться только windows. Решение было грубым но надёжным - просто обрывал прерывания через cli / sti и все. В win 98 можно было напрямую, при переходе на win 2000 пришлось драйвер написать
basilbasilbasil
21.02.2022 02:50Подобные задачи уже были решены для звука уже 13 лет назад в виде готового решения.
https://www.kvraudio.com/news/solid_state_logic_announces_mx4_128_channel_madi_i_o_with_dsp_powered_ssl_software_mixer_11290
даже уже с фильтрами.
каждая карта 64in/64out - можно воткнуть несколько.
И конвертеры есть, тоже готовые (MADI-based)
Может уже и не выпускаются.
В том числе и по сетке (DANTE)
Готовый продукт, с уже готовый стандартом ASIO.
Ant80
заказчики хотели только windows в принципе, или только windows как интерфейс? первая приходящая в голову идея - исполнить realtime часть в чёрном ящике с OS действительно реального времени, с буферизацией данных, а на стороне windows оставить управление и приём данных уже из буфера. скорее всего, там такие стоимости оборудования, что +1 ящик не играет роли. почему решили так не делать?
Jury_78
Да, казалось бы проще объединить АЦП и память в одном устройстве, а результат уже передавать в систему.
Alex_Hitech Автор
Так и было раньше. От этого решения отказались.
Ant80
а почему отказались? очень интересная история, хочется подробностей.
Alex_Hitech Автор
Использовался DSP фирмы Texas Instruments, C6678 "Keystone I". В нём 8 ядер. Одно ядро занималось тем, что получало данные от FPGA по PCIe, шесть занимались применением фильтров к полученным данным, восьмое отправляло всё это богатство в UI через обычный Ethernet. Решение отлично работало на 128 каналах, но уже при 512 каналах начало скрипеть сразу по нескольким параметрам: ширины канала Ethernet перестало хватать, скорости выполнения фильтров перестало хватать, памяти перестало хватать, скорость получения данных из FPGA была на грани допустимого. (Там был PCIe Gen. 1). Можно было заменить DSP на Keystone II или что-то более существенное, поднять скорость Ethernet до 10 гигабит в секунду, перейти на другое подключение, но это увеличивало стоимость продукта, а она и так не низкая. Потом возникла гениальная мысль: почему бы всё, что можно, не перевести на GPU, оставив CPU только менеджмент, и не воткнуть FPGA в слот PCIe компьютера напрямую? Это исключает дорогущий модуль с DSP и, теоретически, должно сильно уменьшить latency. Я взял под козырёк и начал копать в указанном направлении.
Jury_78
Для визуального просмотра в реальном времени такие скорости наверно не нужны и 32 разряда на мониторе не отразить.
Alex_Hitech Автор
Визуальный просмотр в реальном времени нужен. Нейрохирурги умеют реагировать на нужный паттерн на экране, лично убедился. И 32 бита — тоже не просто так придуманное требование; конечно, оно нужно больше для исследователей, чем для клинического применения, но всё равно нужно.
Jury_78
Я не к тому, что вообще не надо, а о том, что человек может увидеть в реальном времени. Нужно ли все это? Понятно, что потом в спокойной обстановке можно что угодно разглядывать.
Alex_Hitech Автор
Вообще-то нужно. Всё дело в том, как показывать.
Если накладывать сигналы друг на друга, то будут хорошо видны повторяющиеся шаблоны, паттерны в сигналах. И внешний вид такого "слоёного пирога" позволяет врачу уверенно знать, в каком конкретно месте мозга сейчас находится электрод, надо ли его вставить глубже или, наоборот, вынуть.
Вот пример. Белый шум от всего шестнадцати сигналов — но видите, как несколько сигналов описывают плавные дуги между 0 и +2 mV? Вот по таким штукам ориентируется в мозгах нейрохирург.
Jury_78
Честь им и хвала, если они в этом способны разобраться!
Schicout
Это годы и годы тренировки и непрерывное самообучение. Вот могу поспорить (если у Вас стаж программистом больше 5-6 лет), что глядя на код, сам код Вы уже не видите. Ну, то есть, видите, конечно, но Ваш мозг уже реагирует на определенные шаблоны и вместе с кодом Вы видите ..., как бы это сказать... процесс и можете легко и с достаточной достоверностью предсказать результат. Может быть Вы процесс увидите раньше, а код, как код, распознаете немного позже, Или посмотрите не него с мыслью - что-то тут фигня какая-то, а саму фигню увидите чуть позже. (Привет, Матрица).
Когда мне студенты приносят на проверку свои работы с иллюстративным материалом (диаграммы фазового равновесия, петли магнитного гистерезиса, какие-то другие специфичные графики) и если в них есть неправильность на уровне логики и/или физики, я могу на полминуты залипнуть с мыслью - а что, собственно, мне здесь не нравится? И нахожу же.
Jury_78
Я правда не программист, но мысль вашу понимаю.
buratino
вообще говоря, если вы говорите про АЦП, то 32 битных АЦП, да еще работающих на таких скоростях, не бывает...
mkarev
Поддерживаю, 2^32 уровней квантования хватит, чтобы залезть в область тепловых шумов компонент РЭА, что сводит на нет всякий смысл АЦП таких разрядностей.
buratino
тепловые шумы небось на уровне 16 бит, а 32 будет уже на уровне дробных долей заряда электрона.. Тут с 12-ю то не знаешь что откуда навелось..
Alex_Hitech Автор
У нас в прошлом продукте 16 разрядов, и этого объективно мало. В новом будут 24 и 32. И ADC такие есть…
buratino
делаем оценку на пальцах. Измеряемые напряжения порядка 10 милливольт. Измеряют обычно измерением напряжения на делителе. Допустим, сопротивление делителя 100 Ом. 1 попугай 32 разрядного АЦП - 2.3*10^-10
Тогда ток, соответствующий 1 попугаю 32 разрядного ацп в вашем случае (10*10^-3 * 2.3*10^-10)/10^2 = 2.3 * 10^-14 А
Один ампер - это один кулон (6.2*10^18 электронов) в секунду.
Найденный выше ток это 2.3 * 10^-14 * 6.2*10^18 = 1.4 * 10^5 электронов. Тээкс, что там у нас со скоростью ? " сорок тысяч замеров с каждого контакта в секунду. " 1.4 * 10^5 электронов поделить на 4*10^4 будет 3.5 электрона. Таким образом элементарный расчет на пальцах показывает, что заявленные характеристики измерительной системы несколько завышены и явно упираются в пределы квантовой механики, и это не считая наводок от работающей аппаратуры, мобильной связи и прочих везде вылазящих 50 Гц.
DjPhoeniX
Хотя и согласен, но замечу, что операционные (тем более нейрохирургические) кабинеты обычно очень хорошо экранируются от любых электромагнитных сигналов, в том числе паразитных наводок от электросети и сотовых станций. По крайней мере должны. Кстати, @Alex_Hitech, и действительно, как организуется питание таких оборудований? Там же любой всплеск на десятки милливольт уже даст нехилую погрешность измерений…
Alex_Hitech Автор
Да, помехи — наш самый главный враг. Иногда приходится выключать кучу не жизненно необходимого оборудования, иногда даже освещение приходится вырубать. (Флюоресцентные трубки дневного света — о-о-о!..)
Alex_Hitech Автор
Я с аппаратной частью не знаком, у нас для этого отдельный железячник есть, я завтра его спрошу. Мы получаем сигналы вот с этих устройств, а сейчас делаем ещё своё собственное устройство.
Но с точки зрения неспециалиста — а разве запрещается пропустить сигнал через усилитель перед тем, как его квантовать и оцифровывать?..
DjPhoeniX
Усилитель в общем случае может только добавить шумов, и чем более усилитель «low-noise», тем дороже. Причём при приближении к нулю цена растёт чуть ли не экспоненциально, а ноль так и не достигается.
buratino
в описании этих устройств черным по белому написано " All signals are amplified and digitized directly on the headstage, so data on the interface cables is purely digital and immune to noise pickup". Т.е. все сигналы усиливаются и оцифровываются на месте. Вот тут есть описание используемого чипа https://intantech.com/products_RHD2000.html и даташит https://intantech.com/files/Intan_RHD2164_datasheet.pdf В описании читаем, что там используется 16 битный АЦП. 64 канала, скорость АЦП 30кГц на канал и стандартный протокол SPI для передачи данных. Чип производит максимум 2байта*30000*64=3.84 Мегабайта данных в секунду. С другой стороны, у вас в ТЗ вероятно стоит "320 мегабайт данных в секунду", 320/3.84*64 =5333. Т.е. для получения заданной скорости передачи данных вам потребуется 5333 электрода и столько же каналов АЦП.
Tarakanator
В смысле не отразить? 12 бит на субпиксель=36бит на пиксель.
Alex_Hitech Автор
Только Windows в принципе. На Linux можно было бы добиться результата с меньшим геморроем и с меньшим latency, но клиенты при слове Linux впадают в кому.
Хотя жалко, потому что нынешняя программа, в отличие от предыдущей, легко портируется на что угодно, а низкая задержка (latency) перед обратной стимуляцией в качестве реакции на определённый входящий сигнал невероятно важна. С Linux`ом мне удалось снизить задержу до 4 миллисекунд, что, в принципе, достаточно для предотвращения эпилептических припадков. Из-под Windows пока не получается снизить меньше чем 6 миллисекунд, это на грани для эпилепсии и слишком долго для болезни Паркинсона.
С другой стороны, я пока в самом начале разработки продукта, так что, может, удастся натянуть сову на глобус и добиться идеальной 1 миллисекунды между генерацией импульса в мозге и отправкой ответной стимуляции обратно в мозг.
Раньше, в предыдущей версии продукта, был отдельный DSP, без операционки вообще, который я программировал, и который выполнял три четверти работы. В новой версии от этого DSP отказались, потому что исчерпали его возможности, а более дорогой DSP ставить не хотят: цену надо снижать, а не увеличивать.
13werwolf13
есть в этом мире несколько человек которые с моей подачи работают на линуксе стилизованном под винду и не знают об этом.. я ни на что не намекаю но...
Alex_Hitech Автор
Я понимаю основную идею, но нет, Windows — объективная необходимость, данная нам в ощущении :-)
sshmakov
Может быть в мире существуют платы с Linux в исполнении PCIe?
Alex_Hitech Автор
Может быть, но нам от этого ни холодно, ни жарко. Плата-то наша собственная, наше проектирование и наше исполнение. Не всё ли равно, что ещё есть в мире, если подключить и запустить нужно конкретно эту?
Schicout
Есть специфическое ПО, разработчики которого принципиально отказываются разрабатывать его для ОС, отличных от Windows. Например. Это, де факто, стандарт обработки и визуализации экспериментальных данных в научных исследованиях - можете посмотреть любой рецензируемый журнал и 3/4 графиков там будет из Origin, причем, зачастую, на дефотных темах. Да, Вы сможете его запустить на виртуальной машине, но когда требуется realtime - это не спасет. ИМХО.
13werwolf13
Это меня всегда удивляло, почему профессиональный софт требующий точности, стабильности и производительности выходит в основном только на ОС которая хуже всех показывает и то и другое..
Jury_78
Мне Linux нравится и я им пользуюсь, но не может столько пользователей Windows ошибаться. Да, во многом привычка, но де до такой же степени.
13werwolf13
Выборка сомнительная, но мой опрос показал такое:
NeoCode
А при словах DSP, DMA, FPGA, PCIe, GPU они не впадают в кому? :)
Я к тому что может клиентам и не обязательно знать технических решений: вот вам компьютер, вот вам специальное приложение на весь экран, запускаемое при включении - включайте и работайте...
Alex_Hitech Автор
Нет, так это не работает, увы. Медицинская техника всё-таки. Надо очень подробно рассказать, что там внутри.
NeoCode
Ну а в чем проблема с альтернативными ОС? Вы подробно рассказываете им про устройство Windows? Может люди лет 30 назад видели какой-то линукс у которого кроме консоли ничего нет, или слышали от кого-то, отсюда и негативное отношение. Может, показ им современного ноутбука, на котором установлен максимально виндоподобный дистрибутив с максимально виндоподобными темами и привычным софтом (тем же матлабом), решил бы проблему?
Я не к тому что линукс был бы лучше в вашей задаче (на самом деле я не знаю), а просто удивило то, что казалось бы такая высокотехнологичная сфера, умные люди, и такие странные, немотивированные ничем кроме инерционности мышления ограничения.
Alex_Hitech Автор
У меня нет никаких проблем с альтернативными ОС, я вон Гайкой занимаюсь в свободное время.
Jury_78
Что б человек что то сделал... непривычное нужен стимул. Пока его нет, и зачем напрягаться?
Alex_Hitech Автор
Не нам стимулировать наших клиентов к изучению Linux`а. Тем более что лично я Linux не люблю :)
Jury_78
Они сами должны решить... Вот, к примеру, заставят (большие начальники) все перевести на отечественную ОС. Вот будет стимул... Хотя стрессов для врачей не хотелось бы.
Tarakanator
Нейрохирурги на ОС, разработчики которой даже лицензии на ОС не соблюдают(исходники закрыли)? Мне страшно. Или у нас сделали ОС linux без нарушения лицензии?
NeoCode
Так я не вас имею в виду, а врачей нейрохирургов:)
Если этот компьютер подключен к столь серьезному оборудованию, то это уже не просто компьютер, а специализированный аппаратно-программный комплекс, с заранее установленным ПО. Какая там ОС никого не должно волновать, он может вообще должен быть полностью закрытый без права втыкать флэшки в USB (а вдруг вирус).
Alex_Hitech Автор
Нет. Один из планируемых видов продаж новой версии устройства — просто плата с источником питания. Студент сможет собрать свой собственный компьютер, отвечающий нашим минимальным требованиям, воткнуть в него нашу плату, загрузить и установить ПО, докупить электроды и, теоретически, сможет проводить исследования на открытом мозге не хуже, чем какой-нибудь НИИ. Но откуда у студента-медика компьютер без Windows? :)
klounader
Ниоткуда, они давно уже с андроид-смартфонами бегают.
pfzim
Больше интересно откуда у него открытый мозг?
Alex_Hitech Автор
Мозг необязательно должен быть человеческим. Большинство исследований мозга выполняются на крысах и мышах, — их мозг очень похож на наш, а стоят они не в пример дешевле.
Mes
А сколько стоит человеческий мозг?
Alex_Hitech Автор
Смотря в какой стране и в каком состоянии. Для исследований ведь не каждый мозг подходит. Нужен живой мозг человека, который страдал от какой-то болезни, перенёс инсульт с повреждением мозга и излечился. У мышек это состояние хотя бы искусственно создавать можно, с людьми так поступать считается негуманным.
YuryZakharov
А как Вы думаете, что с отчисленными студентми происходит?
Tarakanator
мне кажется или либо требования к железу будут очень жёсткими, или это ещё дальше уйдёт от реалтайма?
Как я понимаю даже на своём железе вы не можете гарантировать реалтайма... просто по опыту эксплуатации говорите, что работает достаточно хорошо.... а если другой патч винды, другой чипсет? Не внесёт ли это непредвиденные изменения? Ладно ещё в мозг мышку тыкать, а если человека?
Ant80
я долго мечтал войти в медицину и больше 5 лет пытался работать с врачами. в итоге пришёл к печальному выводу, что это очень трудные во взаимодействии люди. не умеют мыслить структурно, стараются постоянно держать лицо, привыкли к строгой иерархии и за её пределами работать не обучены. так что непреодолимое и авторитарное требование виндовса тут неудивительно.
Alex_Hitech Автор
Вот и у меня такое же впечатление складывается.
klounader
Работа врача не предполагает вариантов «может быть так, а может быть этак», особенно, когда он выписывает лекарство или например ставит заморозку. Для всего есть последовательность в зависимости от поставленной задачи, которую нужно решить согласно уже разработанным методикам. Это терапевту разрешается прописывать арбидол от простуды, чтобы отстали побыстрее, а в нейрохирургии такое не прокатит. Так и работают закалённые человеки в строго последовательном режиме, где шаг влево или вправо равноценно самоубийству.
Ant80
да, это верно, и любое отклонение от разработанных специально обученными людьми методик является смертным грехом, независимо от цены ошибки. и это сложно критиковать, потому мало кто из пациентов хочет, чтобы именно на нём ставили бы опыты с неизвестными исходом.
и этот же подход работает в жизни в целом, за пределами работы.
но я немного о другом.
вот когда пытаешься в рабочей обстановке общаться с врачом, он первым делом решает для себя, кто ты: начальство или младший медперсонал.
если ты начальство, то далее следуют тонны любезности и заверений в глубочайшем почтении и преданности.
а если ты холоп, то поди принеси подотри, подожди два часа под дверью, писать не барское дело, вот тебе обрывочные фразы, конспектируй на лету. задаёшь неудобные вопросы - не тебе, холопу, спрашивать с авторитетов, ты же неграмотен.
все ит-специалисты по умолчанию отнесены к классу холопов.
я немного карикатурно описал, но вот прям как наяву вижу эту историю с линуксом, который объективно лучше, но никто из пользователей не знает, как к нему подойти, а потому нужен виндовс и точка.
klounader
человек существо ленивое и идёт по пути наименьшего сопротивления. обучаться заново чему-то от того, к чему давно привык — это не всегда удобно и не всем нужно.
Schicout
Просто эти люди являются величайшими умами, которые совершенствуются в нейро...логии (не знаю, как назвать). И им IT неинтересно. И это правильно. Они не должны заниматься изучением ОС, консоли и т.п. Все должно быть просто и привычно, как топор, они профессиональные пользователи программно-аппаратных комплексов. Потому, как если они будут отвлекаться на изучение ОС, они будут медленнее развиваться как нейрохирурги и их квалификация будет неизбежно падать. Я бы не хотел, чтобы хирург, который будет меня оперировать (тьфу-тьфу-тьфу, здоровья вам всем и добра) изучал бы какие-то другие методики взаимодействия с компьютером вместо хирургии. А Вы?
Ant80
если посмотреть, например, на аппараты УЗИ, то там с ходу вообще непонятно, какая ОС используется, требования врачи выдвигают только к функционалу аппарата в целом, и не говорят, что у него должно быть под капотом, и это нормально.
mkarev
Это на самом деле очень интересный момент. По идее сабжевый агрегат косвенно несет ответственность за здоровье. А следовательно должен пройти серьезную сертификацию, и до кучи, если является средством измерения внесен в единый гос реестр СИ. И вот в этом процессе подобные архитектурные "решения" следовало бы присекать на корню ИМХО.
d1gital_love
Омерзительно!
Alex_Hitech Автор
Я программист DSP, так что отказ от DSP ударил прежде всего по мне самому. Я тоже считаю, что надо было оставить DSP. Но законы экономики неумолимы: дорогой продукт просто никто не будет покупать, поэтому DSP пошёл под нож.
pvvv
а что там можно можно было на стоимости комплектации сэкономить?
в таком устройстве (тем более медицина) стоимость комплектации разве не какие-то несколько процентов от цены продукта?
Alex_Hitech Автор
Тем не менее, из-за десятка долларов в комплектации финансовый отдел грозится запороть продукт целиком.
Nordicx86
Если уж такая проблема с реальным временем - почему не взять SoC - FPGA + ARM - там же поднять ОСРВ какой нить который занимается первичной обработкой/фильтрацией и там же сделать DMA для прямой трансляции в память GPU.....
Хотя если честно я не понимаю почему нельзя всю обработку делать на FPGA? Xilinx VU9P - сейчас можно тысячи за полторы две баксов Взять - плата, с памятью и нормальным Охлаждением...
Alex_Hitech Автор
Мы строго привязаны к Microsemi Polarfire.