Jump to content

    

Recommended Posts

10 hours ago, Doka said:

я этот момент спецом отмоделировал на срезе AXI stream

Это понятно. А на стороне драйвера? Там можно проверить паттерном в самой ранней точке получения. Если и в HDL-модели всё пучком, и в драйвере - тогда это становится веселее

https://github.com/Xilinx/dma_ip_drivers/blob/017b4bd985cc776ce75b78fc71cfa6bef6afd890/XDMA/linux-kernel/xdma/xdma_cdev.c#L605 - везде слова cdev, интуитивно кажется cdev = char device

Share this post


Link to post
Share on other sites
53 minutes ago, AVR said:

везде слова cdev, интуитивно кажется cdev = char device

Разумеется character. Block device там не нужен, ла и character нужен только для того, чтобы ioctl кидать да mmap сделать

Share this post


Link to post
Share on other sites
On 8/13/2020 at 11:07 AM, gosha-z said:

Я же говорил, алгоритм другой:

1. Открываем chardev

2. Через ioctl запрашиваем максимальный размер блока памяти, который драйвер уже распределил

3. Делаем mmap без предварительного malloc, получаем адрес этого блока в userspace

4. Встаем в epoll-цикл, ждем, когда драйвер нам скажет "Готово, забирай"

read подразумевает под собой копирование данных kernel space -> user space, что есть накладные расходы

Дошёл  я до этой стадии поэтому доп.вопросы:

 

1. Какой таймаут при вызове epoll_wait  задавать?.. милиссикунды - слишком много, либо задавать 0 и использовать нанослип()?

photo_2020-08-20_20-57-32.thumb.jpg.376b7a8cd1e11ddd11dad8546c85fc06.jpg

 

 

 

2. не могу уловить в моём кейсе правильнее будет использовать epoll с событиями по уровню или по фронту. интуитивно кажется, что надо по фронту, но хотелось бы проверить себя

photo_2020-08-20_20-57-27.thumb.jpg.ab0ffb829b4a395fb15a7a5d4aa86869.jpg

photo_2020-08-20_20-57-22.thumb.jpg.de0c8e4afd3215c2e366fceac106daa4.jpg

 

 

3. достаточно ли  epoll_wait или надо использовать вариант функции epoll_pwait ?

 

4. ну и конечно самый концептуальный вопрос: как соотнести выбор таймаута (для epoll_wait), размера пакета и требуемой пропускной способности?!

Мне надо принять (и передать at the same time) порядка 1 ГБайт/с, выбрал размер пакета 4КБ, но чувствуется его придётся поднимать (агреггировать пакеты в ПЛИС, складывая в один большой), чтобы добиться такой прорускной способности.

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

 

 

 

 

Share this post


Link to post
Share on other sites

epoll_wait отваливается по таймауту если не было никаких других событий в этом наборе дескрипторов. Какой вам нужен - зависит от вашей задачи. На скорость передачи это не влияет.

Share this post


Link to post
Share on other sites
On 8/13/2020 at 11:07 AM, gosha-z said:

read подразумевает под собой копирование данных kernel space -> user space, что есть накладные расходы

что это означает?.. не использовать read или альтернатив read всёже нет?!

(примеров epoll без read|write в сети найти не удалось)

11 minutes ago, gosha-z said:

epoll_wait отваливается по таймауту если не было никаких других событий в этом наборе дескрипторов. Какой вам нужен - зависит от вашей задачи. На скорость передачи это не влияет.

тут есть варианты:

минимальное время 1мс - как мне кажется, это ОЧЕНЬ много, выходит либо использовать "0" и нанослип() либо вообще ставить "-1"

Share this post


Link to post
Share on other sites

poll - это всего лишь, образно говоря, некий флаг, который означает, есть данные или нет. Он никоим образом не определяет способ, каким вы эти данные заберете.

Share this post


Link to post
Share on other sites
On 8/20/2020 at 9:26 PM, Doka said:

либо вообще ставить "-1"

Именно так. epoll должен работать без таймаутов в отдельной нитке исполнения. Она должна заниматься исключительно приёмом данных (ну можно ещё попутной обработкой). Всё, что не зависит от данных с карты, должно исполняться в других нитях.

 

NB. Если поток данных с FPGA очень большой, то работа по прерываниям может не сдюжить по требуемым временным ресурсам, придётся делать програмный поллинг (он быстрее, но жрёт 100% CPU)

Share this post


Link to post
Share on other sites
8 hours ago, xvr said:

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

спасибо, это ценная информация.

уточню: нить исполнения - это те функции, что описаны в threads.h так?

 

8 hours ago, xvr said:

NB. Если поток данных с FPGA очень большой, то работа по прерываниям может не сдюжить по требуемым временным ресурсам, придётся делать програмный поллинг (он быстрее, но жрёт 100% CPU)

вот тут как раз интересен практический опыт в разрезе выбора размера пакета для транзакций по PCI-E:выберешь маленький - перегруз процессора по утилизации ресурсов (поллинг), либо вообще пропажа пакетов, а выберешь большой -  увеличивается latency всей цепочки (отправить на ускоритель, обработать, принять с ускорителя), что тоже нехорошо.

 

В реальном кейсе надо принять (и передать at the same time) порядка 1 ГБайт/с,  размер пакета 4КБ наверное будет маловать для "безбедной жизни" на среднем процессоре, но как научиться выбирать такие вещи не ставя множество натурных экспериментов, а эмпирически?!

Share this post


Link to post
Share on other sites

Приветствую!

28 minutes ago, Doka said:

...

вот тут как раз интересен практический опыт в разрезе выбора размера пакета для транзакций по PCI-E:выберешь маленький - перегруз процессора по утилизации ресурсов (поллинг), либо вообще пропажа пакетов, а выберешь большой -  увеличивается latency всей цепочки (отправить на ускоритель, обработать, принять с ускорителя), что тоже нехорошо.

В реальном кейсе надо принять (и передать at the same time) порядка 1 ГБайт/с,  размер пакета 4КБ наверное будет маловать для "безбедной жизни" на среднем процессоре, но как научиться выбирать такие вещи не ставя множество натурных экспериментов, а эмпирически?!

Вопрос не в размере пакета по PCIe  - вопрос в организации  буферов DMA на стороне хоста  -  При стриме данных кольцевой буфер дескрипторов делится на блоки (установкой соответствующих флагов в дескрипторах) только по окончанию пересылки которых и генерируется прерывание.  Размер боков  выбирается исходя из  потока и желаемой/максимальной частоты прерывания.   Как именно  будет организованно вычитка данных  - через копирование из kernel space или  zero-copy через мапинг  user-space памяти в пространство драйвера не столь важно (естественно при достаточной скорости CPU).  Для  обычной системы можно за ориентир брать 500-1000  прерываний в сек.   Для хороших  серверных систем  и до 10К IRQ/s.  Но без экcэкспериментов увы не обойтись.     

 

У меня по такой схеме работало несколько систем с непрерывным потоком 3-6 GByte/s 

 

Удачи! Rob.

Share this post


Link to post
Share on other sites
11 hours ago, Doka said:

) порядка 1 ГБайт/с

мне кажется, при pcie x8 gen3 (не смог найти, какой вы pcie собираете), траффик слабый. Можно легко на прерываниях делать. И размер дескриптора 256 байт.
Я на свой поллинг в отдельном ядре CPU c 100% загрузкой перешел, когда надо было два 10гб порта с высокой нагрузкой в такой pcie пихать. И пришлось размер дескпритора до 512 поднять, чтобы драйвер сильно очередями не нагружать.

Edited by new123

Share this post


Link to post
Share on other sites

Приветствую!

23 minutes ago, new123 said:

мне кажется, при pcie x8 gen3 (не смог найти, какой вы pcie собираете), траффик слабый. Можно легко на прерываниях делать. И размер дескриптора 256 байт.
Я на свой поллинг перешел, когда надо было два 10гб порта с высокой нагрузкой в такой pcie пихать. И пришлось размер дескпритора до 512 поднять, чтобы драйвер сильно очередями не нагружать.

1 ГБайт/с  это как раз поток с одной  10G  в одну сторону.  Прерывание после каждого дескриптора в 256 байт?  4M IRQ/s :wacko2: ??? 
Скорее  всего тут недопонимание  что такое этот "дескриптор"  и его размер.  И опять же тип PCie не играет тут особой роли - это только показывает макс лимит трафика которой вы теоретически можете  прогнать по шине. 

 

Для  выбора  оптимальной схемы работы DMA  важно  понимать  общую картину (схему) dataflow.  Кто шлет данные,  с какой периодичностью, как эти данные группированы, средний/пиковый трафик, требования к latency, ...    

 

Удачи!  Rob.

Share this post


Link to post
Share on other sites
14 hours ago, Doka said:

уточню: нить исполнения - это те функции, что описаны в threads.h так?

Да

14 hours ago, Doka said:

В реальном кейсе надо принять (и передать at the same time) порядка 1 ГБайт/с,

Это немного

14 hours ago, Doka said:

размер пакета 4КБ наверное будет маловать для "безбедной жизни"

А это маловато :)

 

В прерываниях самое плохое их латентность - обработка прерывания + доставка его на User Space (в виде пробуждения нити исполнения) довольно медленный процесс (особенно доставка в User Space)

14 hours ago, Doka said:

но как научиться выбирать такие вещи не ставя множество натурных экспериментов, а эмпирически?!

Никак. Процессоры совершенствуются, ОС тоже развиваются. Несколько лет назад проводили замеры латентности прерываний (на Linux, насколько помню) - порядка нескольких десятков ms (10-20)

Стройте систему так, что бы латентность прерываний не была на критическом пути

 

 

Share this post


Link to post
Share on other sites
2 hours ago, RobFPGA said:

1 ГБайт/с  это как раз поток с одной  10G  в одну сторону

ой да, спасибо, мельком прочитал Гбит

2 hours ago, RobFPGA said:

Прерывание после каждого дескриптора в 256 байт?  4M IRQ/s :wacko2: ??? 
Скорее  всего тут недопонимание  что такое этот "дескриптор"  и его размер

да, я делал после каждого дескриптора. В среднем подсчитал, что средний размер получаемого пакета для моих задач 160-190байт. Подумал 256 байт на дескриптор dma хватит. Но в критические очень моменты, tcp заходит по 1500 байт пачками и пришлось поднять до 512 байт на дескриптор, чтобы кольцо дескприпторов не так быстро заполнялось.

Делать прерывание не после каждого дескриптора, а после накопления N дескрипторов не совсем мой вариант, поэтому перешел на свой поллинг.

Share this post


Link to post
Share on other sites
26.08.2020 в 04:15, RobFPGA сказал:

установкой соответствующих флагов в дескрипторах, только по окончанию пересылки которых и генерируется прерывание

Рабочая схема. Пробовали её, но в итоге нам удобнее оказалось генерировать прерывания по порогу заполнения выходной очереди: драйвер задаёт порог через регистр в дивайсе, и тот мечет прерывания на каждые эн пакетов. Очень эффективный способ получился, особенно на коротких пакетах (т.е. когда их очень много).

Share this post


Link to post
Share on other sites

Приветствую!

55 minutes ago, dxp said:

Рабочая схема. Пробовали её, но в итоге нам удобнее оказалось генерировать прерывания по порогу заполнения выходной очереди: драйвер задаёт порог через регистр в дивайсе, и тот мечет прерывания на каждые эн пакетов. Очень эффективный способ получился, особенно на коротких пакетах (т.е. когда их очень много).

Ну так классика - добавить сюда  еще  таймер чтобы генерировал прерывание по timeout если буфер не пуст но и не заполнен до порога, и будет классический interrupt-coalescin.

В хороших  сетевых картах  это еще дополняется динамической подстройкой timeout и переключением с IRQ на поолинг  при разных нагрузках если требуется малый latency.  

 

Удачи! Rob.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.