我正在写一个多线程的openmpi应用程序,使用MPI_Isend和MPI_Irecv从多个线程在InfiniBand RDMA队伍之间交换每秒数百个消息.
传输大约为400-800KByte,每个等级产生大约9Gbps的输入和输出,完全在FDR的容量范围内.简单的MPI基准测试也表现出良好的性能.
通过在专用线程中使用MPI_Testsome轮询所有活动传输来检查传输的完成.
我实现的传输速率取决于消息速率,但更重要的是取决于MPI_Testsome的轮询频率.也就是说,如果我每隔10毫秒轮询一次,请求的结束时间比我每1毫秒轮询一次.
我希望如果我轮换10ms而不是每1ms,我最多会在9ms之后被告知已完成的请求.我不希望传输本身通过减少对MPI_Testsome的调用来延迟完成,从而减慢总传输速率.我希望MPI_Testsome完全被动.
这里的任何人都知道为什么会出现这种情况?
"DMA"在这里表示:直接内存访问,"RDMA"是:远程直接内存访问.
我使用Java创建了一个传输股票数据的应用程序,但我发现延迟比我预期的要大.我听说有人开发了使用"DMA/RDMA"的相同类型的应用程序,它具有良好的性能,所以我想知道我是否可以在Java中使用"DMA/RDMA"?
如果没有,我应该使用什么语言,以及是否有任何好的库可供使用?
我有一些由Infiniband网络连接的多核计算机.我希望在共享内存池上进行一些低延迟计算,并进行远程原子操作.我知道RDMA是要走的路.在每个节点上,我将注册一个内存区域(和保护域)以进行数据共享.
在线RDMA示例通常关注单线程服务器和单线程客户端之间的单个连接.现在,我希望在每个Infiniband节点上都有一个多线程进程.我对以下内容感到非常困惑......
对于n个节点和m个线程的集群,我应该在每个节点上准备多少个队列对?更具体地说,同一节点上的多个线程可以共享同一个队列对吗?
我应该在每个节点上准备多少个完成队列?我将在每个节点上有多个线程发出远程读/写/ cas操作.如果他们要共享一个公共完成队列,则完成事件将被混淆.如果线程有自己独立的完成队列,那么它们确实会有很多.
你建议我有任何现有的库而不是编写这个软件吗?(嗯,或者我应该写一个并开源吗?:-)
谢谢你的善意建议.
我正在尝试在这里构建和运行RDMA示例.但是因为我正在探索,我没有任何能够管理RDMA的硬件.当我尝试运行示例代码时,我收到这样的错误.
librdmacm: couldn't read ABI version.
librdmacm: assuming: 4
CMA: unable to get RDMA device list
error: ec = rdma_create_event_channel() failed (returned zero/null).
Run Code Online (Sandbox Code Playgroud)
是否有可用于开发的RDMA功能的"本地"实现?我知道RDMA中的"R"意味着远程,但我认为这可能存在用于测试/开发目的.
作为参考,我的Ubuntu 14.04箱尝试这个已经安装的软件包libibverbs-dev
,并librdmacm-dev
为了让代码编译.
我有两台机器,一台客户机和一台服务器,与Infiniband连接.服务器机器有一个NVIDIA Fermi GPU,但客户端机器没有GPU.我有一个在GPU机器上运行的应用程序,它使用GPU进行一些计算.GPU上的结果数据从不被服务器机器使用,而是直接发送到客户端机器而无需任何处理.现在我正在做一个cudaMemcpy
从GPU获取数据到服务器的系统内存,然后通过套接字将其发送到客户端.我正在使用SDP为此通信启用RDMA.
在这种情况下,我是否可以利用NVIDIA的GPUDirect技术来摆脱cudaMemcpy
呼叫?我相信我已正确安装了GPUDirect驱动程序,但我不知道如何在不先将其复制到主机的情况下启动数据传输.
我的猜测是不可能将SDP与GPUDirect结合使用,但还有其他方法可以启动从服务器机器GPU到客户机的RDMA数据传输吗?
额外:如果somone有一个简单的方法来测试我是否正确安装了GPUDirect依赖项,这也是有帮助的!
Linux中有没有像tcpdump这样的实用程序来捕获流经RDMA通道的流量?(Infiniband的/ ROCE /的iWARP)
我正在编写一个RDMA(InfiniBand)内核模块.
到目前为止,我已成功创建保护域,发送和接收队列的完成队列.
但每当我尝试通过调用ib_create_qp来创建队列对时,它都无法创建队列对.我写的代码如下所示:
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/module.h>
#include <linux/err.h>
#include "myClient.h"
struct workqueue_struct *myClient_workqueue;
struct ib_sa_client myClient_sa_client;
/*
static void myClient_add_one(struct ib_device *device);
static void myClient_remove_one(struct ib_device *device);
*/
struct ib_pd *mypd;
struct ib_cq *myrcvcq;
struct ib_cq *myClientsendcq;
struct ib_qp *myClientqp;
void myClient_ib_recvcompletion(struct ib_cq *cq)
{
printk("A user-specified callback that is invoked when a completion event occurs on the CQ.\n");
}
void myClient_ib_sendcompletion(struct ib_cq *cq)
{
printk("A user-specified callback that is invoked when a …
Run Code Online (Sandbox Code Playgroud) 在我的应用程序中,我使用 infiniband 基础设施将数据流从服务器发送到另一个服务器。我过去习惯通过 infiniband 轻松开发 ip,因为我更熟悉套接字编程。到目前为止,性能(最大带宽)对我来说已经足够好了(我知道我没有获得可实现的最大带宽),现在我需要从无限带宽连接中获得更多带宽。
ib_write_bw 声称我的最大可实现带宽约为 1500 MB/s(我没有得到 3000MB/s,因为我的卡安装在 PCI 2.0 8x 中)。
到现在为止还挺好。我使用 ibverbs 和 rdma 对我的通信通道进行了编码,但我得到的带宽远远低于我可以获得的带宽,我什至获得的带宽比使用套接字少一点,但至少我的应用程序不使用任何 CPU 功率:
ib_write_bw:1500 MB/s
套接字:700 MB/s <= 在此测试期间,我的系统的一个核心处于 100%
ibvers+rdma: 600 MB/s <= 在这个测试过程中根本没有使用 CPU
看来瓶颈就在这里:
ibv_sge sge;
sge.addr = (uintptr_t)memory_to_transfer;
sge.length = memory_to_transfer_size;
sge.lkey = memory_to_transfer_mr->lkey;
ibv_send_wr wr;
memset(&wr, 0, sizeof(wr));
wr.wr_id = 0;
wr.opcode = IBV_WR_RDMA_WRITE;
wr.sg_list = &sge;
wr.num_sge = 1;
wr.send_flags = IBV_SEND_SIGNALED;
wr.wr.rdma.remote_addr = (uintptr_t)thePeerMemoryRegion.addr;
wr.wr.rdma.rkey = thePeerMemoryRegion.rkey;
ibv_send_wr *bad_wr = NULL;
if (ibv_post_send(theCommunicationIdentifier->qp, &wr, …
Run Code Online (Sandbox Code Playgroud) 我的小组(一个名为 Isis2 的项目)正在试验 RDMA。我们对缺乏单方面 RDMA 读取的原子性保证的文档感到困惑。在过去的一个半小时里,我一直在寻找有关这方面的任何信息,但无济于事。这包括仔细阅读 rdmamojo.com 上的博客,该博客以回答每个 RDMA 问题而闻名......
在我们关注的情况下,我们希望编写器对始终适合单个缓存行的对象进行原子写入。假设这发生在机器 A 上。然后我们计划在机器 B 上有一个单边原子 RDMA 读取器,它可以从 A 读取大块内存,跨越许多这些对象(但同样,没有对象会被非原子地写入,并且所有内容都将适合某个单个缓存行)。因此 B 读取 X、Y 和 Z,并且这些对象中的每一个都位于 A 上的一个缓存行中,并使用原子写入进行写入。
因此,原子写入将是本地的,但 RDMA 读取将从远程机器到达,并且在没有本地 CPU 参与的情况下完成。
尽管是在远程机器上启动的,我们的单边读取是否与原子本地读取“语义等效”?(我怀疑是这样:否则,单边 RDMA 读取对于曾经修改过的数据将毫无用处......)。“规则”记录在哪里?
当在现代无锁内存上使用单侧 RDMA 时,会出现这样的问题:如果数据对象跨越多个缓存行,远程读取器如何安全地查看其传入数据。
\n在 Derecho 开源多播和复制日志库(位于https://GitHub.com/Derecho-Project上)中,我们有这种模式。写入器 W 被授予写入读取器 R 中的一系列内存的权限。内存已正确固定和映射。现在,假设写入涉及跨越许多缓存行的某种数据向量,这很常见。我们使用一个守卫:一个递增的计数器(也在 RDMA 可访问内存中,但在其他一些缓存行中)。R 旋转,当它看到变化时观察计数器\xe2\x80\xa6,这告诉 R \xe2\x80\x9c 你有一条新消息\xe2\x80\x9d,然后 R 读取向量中的数据。后来我们有第二种模式,R 对 W 说,\xe2\x80\x9c我已经处理完该消息,你可以发送另一条消息。\xe2\x80\x9d
\n我的问题:对于现代内存模型,应该使用哪种 C++ 原子风格来写入向量的内存?这会被称为宽松一致性吗?我希望我的代码能够在 ARM 和 AMD 上运行,而不仅仅是具有强大 TSO 内存模型的英特尔。
\n那么对于我的计数器,当 R 旋转监视计数器更新时,我希望如何声明计数器?是否需要将其声明为获取-释放原子?
\n最后,在 R 观察到计数器已增加之后,就速度或正确性而言,将所有内容声明为宽松的,然后在此处使用内存顺序栅栏是否有任何优点?我的想法是,通过第二种方法,我在所有 RDMA 内存上使用最小一致性模型(并对所有此类内存使用相同的模型),而且我只需要在观察到计数器增加后调用成本更高的内存顺序栅栏。因此,在访问我的向量之前,它只发生一次,而每次我的轮询线程循环时,获取释放原子计数器都会触发内存防护机制。对我来说,这听起来非常昂贵。
\n最后一个想法又引出了一个问题:我是否也必须将此内存声明为易失性,以便 C\xe2\x80\x94 编译器意识到数据可以在其脚下更改,或者编译器本身可以看到数据就足够了std::原子类型声明?在Intel上,对于全店订购,肯定需要TSO加上易失性。
\n[编辑:新信息](我试图在这里吸引一些帮助!)
\n一种选择似乎是将 RDMA 内存区域声明为 std::atomic<relaxed_consistency> 但每次我们的谓词评估线程重新测试防护时都使用锁(在 RDMA 内存中,将使用相同的宽松属性进行声明) )。我们将保留 C++ 易失性注释。
\n原因是,使用具有获取-释放语义的锁,内存一致性硬件将被警告它需要隔离先前的更新。锁本身(互斥体)可以声明为谓词线程本地的,然后将存在于本地 DRAM 中,这是便宜的,并且由于这不是任何东西争用的锁,因此锁定它可能与 test_and_set 一样便宜,并且解锁只是写入 0。如果谓词为 true,我们的触发代码体将在访问锁之后运行(可能是在锁释放之后),因此我们建立所需的顺序以确保硬件将获取受保护的对象使用实际的内存读取。但是,通过谓词测试的每个周期(每次“旋转”),我们最终都会对每个谓词执行锁定获取/释放。所以这会导致一些速度减慢。
\n选项二看似开销较小,也将 RDMA 区域声明为具有宽松一致性的 std::atomic,但省略了锁并像我们现在一样进行测试。然后,当谓词测试为真时,我们将使用语义执行显式内存栅栏(std::memory-order)。我们得到相同的屏障,但仅在谓词评估为 true 时才支付成本,因此开销更少。
\n但现在我们遇到了一个不同类型的问题。Intel 有总存储顺序 TSO,并且由于任何线程都会执行一些先写后读操作,Intel …