Cuda NVCC没有';t展开小型嵌套循环

Cuda NVCC没有';t展开小型嵌套循环,cuda,Cuda,我想知道,为什么NVCC不能为小矩阵(N=4)展开下面的Cholesky分解内核 显然,循环没有展开,并且使用了昂贵的本地内存(我的目标是只在寄存器中执行所有操作) 我这样调用函数: T l[N*N]; for(int i = 0; i < N*N; ++i){ l[i] = buffer[offset+i]; } choleskyKernel2<T,N>(l); for(int i = 0; i < N*N;

我想知道,为什么NVCC不能为小矩阵(N=4)展开下面的Cholesky分解内核

显然,循环没有展开,并且使用了昂贵的本地内存(我的目标是只在寄存器中执行所有操作)

我这样调用函数:

    T l[N*N];
    for(int i = 0; i < N*N; ++i){
        l[i] = buffer[offset+i];
    }

    choleskyKernel2<T,N>(l);

    for(int i = 0; i < N*N; ++i){
        buffer[offset+i] =  l[i];
    }
tl[N*N];
对于(int i=0;i
有没有一种方法可以正确地展开这个循环,这样所有的事情都可以在寄存器中完成

编辑:

完整代码:

#include <thrust/device_vector.h>

template<typename T, int N>
__device__ inline
void choleskyKernel2(T* C){
#pragma unroll
    for (int i = 0; i < N; i++){
#pragma unroll
        for (int j = 0; j <= i; j++) {
            double s = 0;
#pragma unroll
            for (int k = 0; k < j; k++){
                s += C[i*N+k] * C[j*N+k];
            }
            s = C[i*N+j] - s;
            C[i*N+j] = (i == j) ?
                        sqrt(s) :
                        (1.0 / C[j*N+j] * (s));
        }
    }
}

template<typename T, int N>
__global__ static
void test3(T* buffer){
    const int matrixElements = N * N;

    T l[matrixElements];
    for(int i = 0; i < matrixElements; ++i){
        l[i] = buffer[i];
    }

    choleskyKernel2<T,N>(l);

    for(int i = 0; i < matrixElements; ++i){
        buffer[i] =  l[i];
    }
}

int main(){
     thrust::device_vector<double> d_data(16);
     test3<double,4> <<< 1,1 >>>(thrust::raw_pointer_cast(d_data.data()));
}
#包括
模板
__设备在线
空核2(T*C){
#布拉格展开
对于(int i=0;i
虽然我无法告诉您为什么nvcc(或者实际上是代表nvcc执行设备代码编译的cicc)没有展开您的循环,但我可以向您展示如何更改代码以使其展开

转向

#pragma展开
对于(int i=0;i对于(int j=0;j),只有CUDA编译器的维护人员才能肯定地回答这个问题。然而,一些常见的编译器展开试探法是:(1)从展开最内层循环开始(2)在编译时使用已知的“小”跳闸计数完全展开循环(3)使用“大”跳闸计数部分展开循环。最内层循环具有“小”跳闸计数但是可变跳闸计数,因此会使条件(2)和(3)失效。为什么不为(int j=0;ji)break;
?目标是创建一个与编译器的展开启发式方法匹配的控制流。历史上,CUDA编译器不擅长使用
break
语句展开循环,在这种情况下,这似乎仍然是正确的。真的吗?我的意思是,一个具有固定数量的迭代且不干扰循环的循环身体中的计数器?展开不是很简单吗?或者更确切地说,你确定nvcc不擅长展开这些吗?对人类来说可能很简单,对一台没有编程的机器来说很难。试试看。。。
    T l[N*N];
    for(int i = 0; i < N*N; ++i){
        l[i] = buffer[offset+i];
    }

    choleskyKernel2<T,N>(l);

    for(int i = 0; i < N*N; ++i){
        buffer[offset+i] =  l[i];
    }
#include <thrust/device_vector.h>

template<typename T, int N>
__device__ inline
void choleskyKernel2(T* C){
#pragma unroll
    for (int i = 0; i < N; i++){
#pragma unroll
        for (int j = 0; j <= i; j++) {
            double s = 0;
#pragma unroll
            for (int k = 0; k < j; k++){
                s += C[i*N+k] * C[j*N+k];
            }
            s = C[i*N+j] - s;
            C[i*N+j] = (i == j) ?
                        sqrt(s) :
                        (1.0 / C[j*N+j] * (s));
        }
    }
}

template<typename T, int N>
__global__ static
void test3(T* buffer){
    const int matrixElements = N * N;

    T l[matrixElements];
    for(int i = 0; i < matrixElements; ++i){
        l[i] = buffer[i];
    }

    choleskyKernel2<T,N>(l);

    for(int i = 0; i < matrixElements; ++i){
        buffer[i] =  l[i];
    }
}

int main(){
     thrust::device_vector<double> d_data(16);
     test3<double,4> <<< 1,1 >>>(thrust::raw_pointer_cast(d_data.data()));
}
#pragma unroll
    for (int i = 0; i < N; i++){
#pragma unroll
        for (int j = 0; j <= i; j++) {
#pragma unroll
    for (int i = 0; i < N; i++) {
#pragma unroll
        for (int j = 0; j < N; j++)
            if (j <= i) {