我正在尝试为gPb算法实现构建与图像中每个像素相对应的无符号字符直方图数组。我无法解决cudaMalloc调用的崩溃问题。我已经浏览了其他类似的问题,并且始终测试了先前的操作是否返回了cudaSuccess。这是我的代码:
首先,我在类CudaImage的构造函数中分配此结构:
bool CudaImage::create2DHistoArray()
{
//preparing histograms
m_LastCudaError = cudaMalloc((void**)&m_dHistograms, (m_Height + 2 * m_Scale) * sizeof(unsigned int*));
if (m_LastCudaError != cudaSuccess)
return false;
//set all histograms to nullptr
m_LastCudaError = cudaMemset(m_dHistograms, 0, (m_Height + 2 * m_Scale) * sizeof(unsigned int*));
if (m_LastCudaError != cudaSuccess)
return false;
return true;
}
然后在某个时候我将调用一个成员函数来分配一些m_dHistograms [i],如下所示:
bool CudaImage::initializeHistoRange(int start, int stop)
{
for (int i = start; i < stop; ++i) {
m_LastCudaError = cudaMalloc((void**)&m_dHistograms[i], 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
if (m_LastCudaError != cudaSuccess) {
return false;
}
//set all pixels in the gradient images to 0
m_LastCudaError = cudaMemset(m_dHistograms[i], 0, 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
if (m_LastCudaError != cudaSuccess)
return false;
}
return true;
}
最后一个函数中的第一个cudaMalloc崩溃,没有任何警告。使用cuda-memcheck运行时,出现以下消息:
“从主机取消引用统一内存时,应用程序可能会遇到错误。请在主机调试器下重新运行该应用程序以捕获此类错误。”
有人可以帮忙吗?另一个问题是数组分配是否正确实现。我不想从一开始就分配所有内存,因为它会太多,所以我在构造函数(第一个函数)中仅分配了指向数组行的指针,然后在应用程序中在需要时分配了内存并释放了什么我不需要。
答案 0 :(得分:1)
您将遇到段错误,因为在主机代码中读取或修改m_dHistograms[i]
的值是非法的,因为它是在设备内存中分配的。您需要做的是这样的:
bool CudaImage::initializeHistoRange(int start, int stop)
{
for (int i = start; i < stop; ++i) {
// Allocated memory
unsigned int* p;
m_LastCudaError = cudaMalloc((void**)&p, 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
if (m_LastCudaError != cudaSuccess) {
return false;
}
//set all pixels in the gradient images to 0
m_LastCudaError = cudaMemset(p, 0, 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
if (m_LastCudaError != cudaSuccess)
return false;
}
// Transfer address of allocation to device
m_LastCudaError = cudaMemcpy(m_dHistograms + i, &p, sizeof(unsigned int *), cudaMemcpyHostToDevice);
if (m_LastCudaError != cudaSuccess)
return false;
}
return true;
}
[免责声明:请勿编译或运行,使用风险自负]
此处分配地址存储在主机变量中,该主机变量在完成分配和memset操作后最终复制到设备阵列。这会导致每分配一个额外的主机到设备内存传输的代价。
答案 1 :(得分:0)
我找到的解决方案是借助this stackoverflow answer。代码如下:
bool CudaImage::initializeHistoRange(int start, int stop)
{
for (int i = start; i < stop; ++i) {
m_LastCudaError = cudaMalloc((void**)&m_hHistograms[i], 256 * 2 * m_ArcNo * (m_Width + 2 * m_Scale) * sizeof(unsigned int));
if (m_LastCudaError != cudaSuccess) {
return false;
}
cudaMemcpy(m_dHistograms, m_hHistograms, stop * sizeof(unsigned int*), cudaMemcpyHostToDevice);
if (m_LastCudaError != cudaSuccess)
return false;
}
return true;
}
bool CudaImage::create2DHistoArray()
{
m_LastCudaError = cudaMalloc((void**)&m_dHistograms, (m_Height + 2 * m_Scale) * sizeof(unsigned int*));
if (m_LastCudaError != cudaSuccess)
return false;
m_hHistograms = (unsigned int**)malloc((m_Height + 2 * m_Scale) * sizeof(unsigned int*));
return true;
}
那是我在主机成员中使用了另一个成员,该成员可以帮助我在设备中创建内存。在算法操作期间释放内存的代码是:
void CudaImage::deleteFromHistoMaps(int index) {
//I need some more device memory
if (index + m_Scale + 1 < m_Height + 2 * m_Scale) {
initializeHistoRange(index + m_Scale + 1, index + m_Scale + 2);
}
//device memory is not needed anymore - free it
if (index >= m_Scale + 1) {
cudaFree(m_hHistograms[index - m_Scale - 1]);
m_hHistograms[index - m_Scale - 1] = nullptr;
}
}