Mvapich在内核运行时在CUDA内存上僵局
MVAPICH deadlocks on CUDA memory while kernel is running
我尝试获得一个与mvapich cuda8一起工作的MPI-CUDA程序。我以前确实使用OpenMPI成功运行了该程序,但是我想测试是否在Mvapich获得更好的性能。不幸的是,如果使用MVAPICH时CUDA内核同时运行。
同一运行。我下载了mvapich2-2.2并用配置标志
从源构建态启用MPI调用CUDA内存。Mcast被禁用,因为我无法没有标志。
我在运行应用程序之前使用以下标志:
export MV2_USE_CUDA=1
export MV2_GPUDIRECT_GDRCOPY_LIB=/path/to/gdrcopy/
export MV2_USE_GPUDIRECT=1
mpi_isend/recv同时运行cuda内核时工作正常。但是在我的程序中,MPI在内核正在运行时将数据发送并接收到GPU内存的数据很重要。
我提出了这一行为的两个可能原因。首先,由于某些原因,Mvapich试图运行自己的CUDA内核来从GPU内存发送数据,并且由于GPU已经充分利用,因此该内核不会被安排。第二种可能性:Mvapich使用cudamemcpy某处(不是异步版本),该版本会阻止内核完成执行。
有人可以确认我的假设之一吗?Mvapich中是否有一个我不知道的问题?
编辑:
在这里,一个" simpel"代码说明了我的问题。使用OpenMPI执行代码时,它可以正确执行并终止。使用mvapich2,它在标记的mpi_send函数处僵硬。
#include <stdio.h>
#include <stdlib.h>
#include <cuda.h>
#include <mpi.h>
__global__ void kernel(double * buffer, int rank)
{
volatile double *buf = buffer;
if(rank == 0){
while(buf[0] != 3){}
} else {
while(buf[0] != 2){}
}
}
int main(int argc, char **argv)
{
double host_buffer[1];
MPI_Init(&argc, &argv);
int world_size, world_rank;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
printf("Im rank %dn", world_rank);
cudaSetDevice(world_rank);
double * dev_buffer;
cudaError_t err = cudaMalloc(&dev_buffer, sizeof(double));
if(world_rank == 0){
host_buffer[0] = 1;
cudaError_t err = cudaMemcpy(dev_buffer, host_buffer, sizeof(double), cudaMemcpyHostToDevice);
MPI_Send(dev_buffer, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD);
printf("[%d]First send does not deadlockn", world_rank);
}else {
MPI_Recv(dev_buffer, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("[%d]Received first messagen", world_rank);
}
cudaStream_t stream, kernel_stream;
cudaStreamCreate(&stream);
cudaStreamCreate(&kernel_stream);
printf("[%d]launching kerneln", world_rank);
kernel<<<208, 128, 0, kernel_stream>>>(dev_buffer, world_rank);
if(world_rank == 0){
//rank 0
host_buffer[0] = 2;
cudaMemcpyAsync(
dev_buffer, host_buffer, sizeof(double),
cudaMemcpyHostToDevice,
stream
);
cudaStreamSynchronize(stream);
printf("[%d]Send messagen", world_rank);
MPI_Send(dev_buffer, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD); //mvapich2 deadlocks here
printf("[%d]Message sentn", world_rank);
printf("[%d]Receive messagen", world_rank);
MPI_Recv(dev_buffer, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("[%d]Message receivedn", world_rank);
cudaStreamSynchronize(kernel_stream);
printf("[%d]kernel finishedn", world_rank);
} else {
//rank 1
printf("[%d]Receive messagen", world_rank);
MPI_Recv(dev_buffer, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
printf("[%d]Message receivedn", world_rank);
cudaStreamSynchronize(kernel_stream);
printf("[%d]kernel finishedn", world_rank);
host_buffer[0] = 3;
cudaMemcpyAsync(
dev_buffer, host_buffer, sizeof(double),
cudaMemcpyHostToDevice,
stream
);
cudaStreamSynchronize(stream);
printf("[%d]Send messagen", world_rank);
MPI_Send(dev_buffer, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD);
printf("[%d]Message sentn", world_rank);
}
printf("[%d]Stopped executionn", world_rank);
MPI_Finalize();
}
我回到了这个问题,并使用GDB来调试代码。
显然,问题是在src/mpid/ch3/channels/mrail/src/gen2/ibv_send.c中实现的MVAPICH2的急切协议。急切的协议使用没有异步的CUDA_MEMCPY,该协议将阻止内核执行完成。
问题中发布的程序通过将MV2_IBA_EAGER_THRESHOLD 1传递给Mpirun来运行良好。这样可以防止MPI使用急切的协议并使用Rendez-vous协议。
修补MVAPICH2源代码也确实解决了问题。我将同步的cudamemcpys更改为文件中的cudamemcpyasync
- src/mpid/ch3/channels/mrail/src/gen2/ibv_send.c
- src/mpid/ch3/channels/mrail/src/gen2/ibv_recv.c
- src/mpid/ch3/src/ch3u_request.c
仅需要mpi_isend/mpi_irecv中的第三个文件中的更改。其他MPI功能可能需要一些其他代码更改。
- 将字符串存储在c++中的稳定内存中
- C++ 指针的内存地址和指向数组的内存地址如何相同?
- Win32编译器选项和内存分配
- 当vector是tje全局变量时,c++中vector的内存管理
- 带内存和隔离功能的SQLite
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 迭代时从向量和内存中删除对象
- 在C++中打印指向不同基元数据类型的指针的内存地址
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 多个文件的内存分配错误"在抛出 'std :: bad_alloc' what (): std :: bad_alloc 的实例后终止调用" [C++]
- 为什么示例代码访问IUnknown中已删除的内存
- 如何在C++类内存结构中创建"spacer"?
- 从构造函数抛出异常时如何克服内存泄漏
- malloc() 可能出现内存泄漏
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 如何针对特定情况调试和修复此双自由内存损坏问题
- 类型总是使用其大小存储在内存中吗
- 有没有一种方法可以测量c++程序的运行时内存使用情况
- Mvapich在内核运行时在CUDA内存上僵局