C : Какой слабый атомарный элемент использовать для буферов, которые получают асинхронность. Переводы RDMA?

#c #c 17 #rdma #relaxed-atomics

Вопрос:

Система Derecho (библиотека C с открытым исходным кодом для репликации данных, распределенной координации, Paxos-сверхбыстрая) построена на основе асинхронных сетевых примитивов RDMA. Отправители могут записывать в приемники без паузы, используя передачу RDMA в память приемника. Обычно это делается в два этапа: мы передаем байты данных за одну операцию, затем уведомляем получателя, увеличивая счетчик или устанавливая флаг: «сообщение 67 готово для вас, сейчас». Вскоре получатель заметит, что сообщение 67 готово, и в этот момент он получит доступ к байтам этого сообщения.

Предполагаемая семантика: «просмотр обновленного счетчика должен означать, что код получателя на C увидит байты сообщения». В терминах PL нам нужен барьер памяти между обновлением guard и байтами сообщения. Отдельные строки кэша также должны быть последовательно согласованы: моя защита будет проходить через значения, такие как 67, 68,…. и я не хочу, чтобы какая-либо форма размытого значения или немонотонной последовательности, например, могла возникнуть, если C считывает устаревшую строку кэша или ошибочно хранит устаревшее значение в памяти. То же самое касается самого буфера сообщений: эти байты могут перезаписывать старые байты, и я не хочу видеть какой-либо мэшап.

В этом суть моего вопроса: мне нужен слабый атом, который будет устанавливать [точно] необходимый барьер, не вводя ненужных накладных расходов. Какая аннотация была бы уместна? Будет ли слабая атомарная аннотация такой же для «сообщения», как и для счетчика («охранника»)?

Вторичный вопрос: Если я объявлю свой буфер с соответствующим слабым атомом, нужно ли мне также говорить, что он «энергозависим», или C поймет это, потому что память была объявлена слабо атомной?

Комментарии:

1. На первый взгляд мне кажется, что дополнительной нагрузки на охрану достаточно. Это предотвращает появление любых загрузок данных до обновления guard. После этого кажется, что можно безопасно считывать сами данные как обычные нагрузки, поскольку они не должны происходить в каком-либо определенном порядке; нет volatile или atomic не нужны здесь. Предположительно, на другом конце есть хранилище, которое сигнализирует отправителю, что можно перезаписать буфер, и это хранилище должно быть освобождено.

2. Если буфер должен быть не кэшируемым, чтобы чтение попадало в оперативную память, а не в ваш кэш, это между вами и вашей операционной системой или оборудованием; C не предоставляет возможности контролировать это.

3. Очень полезно. Спасибо, Нейт!

Ответ №1:

Атомарный счетчик, независимо от его типа, ничего не гарантирует в отношении памяти, не контролируемой процессором. Прежде чем начнется передача RDMA, вам нужно убедиться, что кэш ЦП для региона RDMA сброшен и признан недействительным, а затем, конечно, не будет считываться или записываться в этот регион во время передачи RDMA. Когда устройство RDMA подаст сигнал о завершении передачи, вы сможете обновить счетчик.

Поток, ожидающий увеличения счетчика, не должен переупорядочивать какие-либо загрузки или хранилища, выполняемые после считывания счетчика, поэтому правильный порядок памяти std::memory_order_acquire . Таким образом, в принципе, вы хотите заказать получение выпуска, хотя в потоке, который обновляет счетчик, нет ничего, что можно было бы «выпустить».

Вам не нужно создавать буферы volatile ; в общем, вам не следует полагаться на volatile атомарность.

Комментарии:

1. Однако в качестве замечания мы, безусловно, можем прочитать регион во время передачи RDMA: подсистема памяти по-прежнему будет последовательной в кэш-строке, что достаточно для обеспечения определенной безопасности. Например, наша переменная guard всегда будет выдавать значение, которое было записано в какой-то законный момент времени, и будет продвигаться монотонно, потому что автор продвигает его монотонно.

2. Я не знаю подробностей устройств RDMA, которые вы используете, поэтому вам лучше знать, как они работают. Однако в целом вам следует быть осторожным, делая предположения; например, учтите, что, если область RDMA помечена как кэшируемая, выполнение последовательных операций чтения может привести к тому, что предварительный процессор в вашем процессоре начнет считывать данные раньше фактических инструкций по загрузке.

3. Согласованный. Так мы рассуждали, когда помечали эту область памяти как изменчивую, но с новой слабой атомикой и устаревшим представлением о изменчивости мы поняли, что наш старый подход в конечном итоге перестанет работать правильно! Мои студенты изучают точную семантику выпуска-приобретают свойство памяти, но вы меня убедили!