我在嘗試使CUDA程序按其索引管理lambda數組時遇到了問題。能重現問題CUDA C++ 11,lambdas數組,按索引功能,不起作用
#include <cuda.h>
#include <vector>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <cassert>
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true){
if (code != cudaSuccess) {
fprintf(stderr,"GPUassert: %s %s %d\n",
cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
template<typename Lambda>
__global__ void kernel(Lambda f){
int t = blockIdx.x * blockDim.x + threadIdx.x;
printf("device: thread %i: ", t);
printf("f() = %i\n", f());
}
int main(int argc, char **argv){
// arguments
if(argc != 2){
fprintf(stderr, "run as ./prog i\nwhere 'i' is function index");
exit(EXIT_FAILURE);
}
int i = atoi(argv[1]);
// lambdas
auto lam0 = [] __host__ __device__(){ return 333; };
auto lam1 = [] __host__ __device__(){ return 777; };
// make vector of functions
std::vector<int(*)()> v;
v.push_back(lam0);
v.push_back(lam1);
// host: calling a function by index
printf("host: f() = %i\n", (*v[i])());
// device: calling a function by index
kernel<<< 1, 1 >>>(v[i]); // does not work
//kernel<<< 1, 1 >>>(lam0); // does work
gpuErrchk(cudaPeekAtLastError());
gpuErrchk(cudaDeviceSynchronize());
return EXIT_SUCCESS;
}
與
nvcc -arch sm_60 -std=c++11 --expt-extended-lambda main.cu -o prog
運行時,我得到的錯誤編譯一個示例代碼是
➜ cuda-lambda ./prog 0
host: f() = 333
device: GPUassert: invalid program counter main.cu 53
看來,CUDA不能管理中的int(*)()函數指針形式(而主機c + +確實工作正常)。另一方面,每個lambda都是作爲不同的數據類型來管理的,無論它們在代碼中是否相同並且具有相同的合同。那麼,我們如何在CUDA中通過索引實現功能?
如果您的代碼正常工作,將導致替代路徑(無法內聯),這是處理GPU時不需要的行爲。也許相反,你可以創建一個數組的內核/內核調用的lambda設置在編譯時的值? –
請看看,假設可以創建一個__全局__ lambdas的數組。 –
我很肯定你是依賴於CUDA解析器中的一些靜態編譯器分析魔法,當lambda被放入容器時它會中斷。 – talonmies