使用cuDNN执行FFT卷积时出现CUDNN_STATUS_NOT_SUPPORTED错误
CUDNN_STATUS_NOT_SUPPORTED的原因 你遇到的这个问题很典型——自动选择算法或用Winograd能正常运行,但手动指定FFT就卡在cudnnGetConvolutionForwardWorkspaceSize报错,结合你的环境(CUDA 9.1 + cuDNN 7 + sm_35架构),核心原因是手动指定的FFT算法和你的输入参数、硬件架构存在兼容性不匹配,下面具体拆解几个可能的诱因和排查方向:
1. FFT卷积的输入/卷积核维度约束
cuDNN的FFT卷积实现对输入张量尺寸、卷积核大小有严格限制,尤其是在cuDNN 7版本中:
- 输入的高度/宽度(NCHW格式中的H/W)可能需要满足对齐要求,比如必须是2的幂次,或者不能小于某个阈值(比如小于8x8的小尺寸输入,FFT算法效率极低,cuDNN直接不支持手动指定);
- 卷积核的尺寸也有限制,部分FFT实现仅支持3x3、5x5这类常见尺寸,如果你用了7x7或非正方形卷积核,手动指定FFT就会触发不支持错误。
你可以先打印出输入张量维度(N, C, H, W)和卷积核维度(K, C, KH, KW),对照cuDNN 7的官方文档确认是否符合FFT卷积的支持条件。
2. 硬件架构(sm_35)的限制
你编译时指定的-arch=sm_35对应Kepler架构GPU,而cuDNN 7中,FFT卷积的部分实现仅对更高版本的架构(比如sm_50+的Maxwell及以上)提供支持。自动选择算法时,cuDNN会检测硬件架构,自动跳过不支持的FFT算法,转而选择Winograd或其他兼容实现;但手动指定时,cuDNN不会做兼容性判断,直接返回NOT_SUPPORTED。
如果你的GPU实际支持更高架构(比如显卡是Maxwell或以上),可以尝试把编译参数改成-arch=sm_50(或对应你的GPU架构的版本),再测试手动指定FFT是否可行。
3. cuDNN 7版本的特定约束
cuDNN 7和CUDA 9.1的组合存在一些已知的FFT卷积限制:
- 不支持分组卷积(group count > 1)的FFT实现,如果你的卷积是分组卷积,手动指定FFT必然报错;
- 部分FFT实现不支持带bias的卷积,如果你开启了bias参数,也可能触发不支持错误;
- 输入通道数(C)如果不是特定值(比如1、3、16这类常见值),也可能导致FFT算法不兼容。
快速排查方法
你可以通过cudnnGetConvolutionForwardAlgorithm_v7函数获取当前参数下cuDNN支持的所有前向卷积算法,看看FFT算法是否在列表中:
#include <cstdio> #include <cudnn.h> // 假设你已经初始化了cudnnHandle、inputDesc、filterDesc、convDesc、outputDesc cudnnConvolutionFwdAlgoPerf_t perfResults[CUDNN_CONVOLUTION_FWD_ALGO_COUNT]; int returnedAlgoCount; cudnnStatus_t status = cudnnGetConvolutionForwardAlgorithm_v7( cudnnHandle, inputDesc, filterDesc, convDesc, outputDesc, CUDNN_CONVOLUTION_FWD_ALGO_COUNT, &returnedAlgoCount, perfResults ); if (status == CUDNN_STATUS_SUCCESS) { printf("Supported convolution algorithms:\n"); for (int i = 0; i < returnedAlgoCount; ++i) { printf(" %d. %s (Memory required: %.2f KB)\n", i+1, cudnnGetAlgorithmName(perfResults[i].algo), perfResults[i].memory / 1024.0f); } }
如果输出里没有CUDNN_CONVOLUTION_FWD_ALGO_FFT或CUDNN_CONVOLUTION_FWD_ALGO_FFT_TILING,就说明你的参数/硬件确实不支持手动指定FFT卷积。
内容的提问来源于stack exchange,提问作者Kevinj22

