CUDA,不能为数组指定新的初始值设定项

CUDA, a new initializer may not be specified for an array

本文关键字:不能 数组 CUDA      更新时间:2023-10-16

所以我目前有这段代码,但在编译时遇到了一个错误,即"可能没有为数组指定新的初始值设定项",但我在代码中没有声明新数组的位置。所以我不确定这个问题是在哪里以及如何发生的。这是我认为问题所在的代码部分…

struct indvPasswords
{
    int blockId;
    int threadId;
    list<char[1024]> passwords;
};
//22,500 individual blocks
int gridSize = 150;
//1024 threads contained within each block
int blockSize = 32;
int totalNumThreads = (gridSize*gridSize)*(blockSize*blockSize);
indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];

这是所有的源代码。它目前使用cuda查找字典密码。。。

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <stdio.h>
#include <iostream>
#include <fstream>
#include <string>
#include <list>
using namespace std;
//////////////////////////////
//          Constants       //
//////////////////////////////
string password = "C:\Users\james\Desktop\password.txt";
string passwordListFile = "C:\Users\james\Desktop\10millionpasswordlist.txt";
struct indvPasswords
{
    int blockId;
    int threadId;
    list<char[1024]> passwords;
};
//22,500 individual blocks
int gridSize = 150;
//1024 threads contained within each block
int blockSize = 32;
int totalNumThreads = (gridSize*gridSize)*(blockSize*blockSize);
indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];

//Some serial setup first
string passwordFile()
{
    string pwd = "";
    ifstream fileStream(password);
    if (fileStream.is_open()) {
        getline(fileStream, pwd);
        if (pwd != "") {
            //Found a password
            fileStream.close();
        }
        else {
            cout << "No password found in file" << 'n';
        }
    }
    else {
        cout << "Cannot open password file" << 'n';
    }
    return pwd;
}
list<string> readPasswordList()
{
    //open password list
    string line = "";
    ifstream fileStream(passwordListFile);
    list<string> passwordList;
    if (fileStream.is_open()) {
        while (getline(fileStream, line)) {
            passwordList.push_back(line);
        }
    }
    else {
        cout << "Cannot open password file" << 'n';
    }
    return passwordList;
}
void indexing()
{
    list<string> passwords = readPasswordList();
    int sizeOfList = passwords.size();
    int modulus = sizeOfList%gridSize;
    int runFlag = 0;
    if (modulus != 0) {
        //not evenly divided, pass overflow to first block
        //Take the modulus off the size of password list, i.e. 
        //take a number of passwords from the top of the list.
        //Temporarily store the passwords removed and give them 
        //as additional work to the first block.
        list<string> temp;
        for (int i = 0; i < modulus; i++) {
            temp.push_back(passwords.front());
            passwords.pop_front();
        }
        //Now evenly divide up the passwords amoungst the blocks
        int numEach = passwords.size();
        //The first for loop, iterates through each BLOCK within the GRID
        for (int i = 0; i < (gridSize*gridSize); i++) {
            //Set flag, for single run of first block list
            if (i == 0) {
                runFlag = 1;
            }
            //The second loop, iterates through each THREAD within the current BLOCK
            for (int j = 0; j < (blockSize*blockSize); j++){
                //setup the indexes
                pointerToPass[i].blockId = i;
                pointerToPass[i].threadId = j;
                //The third loop, copies over a collection of passwords for each THREAD 
                //within the current BLOCK
                for (int l = 0; l < numEach; l++) {
                    //Add the temporary passwords to the first block
                    if (runFlag == 1) {
                        for (int x = 0; x < temp.size(); x++){
                            //Convert
                            string tmp = temp.front();
                            char charTmp[1024];
                            strcpy(charTmp, tmp.c_str());
                            pointerToPass[i].passwords.push_back(charTmp);
                            temp.pop_front();
                        }
                        //Now never block run again
                        runFlag = 0;
                    }
                    //convert the passwords from string to char[] before adding
                    string tmp = passwords.front();
                    char charTmp[1024];
                    strcpy(charTmp, tmp.c_str());
                    pointerToPass[i].passwords.push_back(charTmp);
                    //now delete the item from passwords that has just been transfered
                    //over to the other list
                    passwords.pop_front();
                }
            }
        }
    }
    else {  
        //Start to transfer passwords
        //First calculate how many passwords each thread will be given to check
        int numEach = sizeOfList / totalNumThreads;
        //The first for loop, iterates through each BLOCK within the GRID
        for (int i = 0; i < (gridSize*gridSize); i++) {
            //The second loop, iterates through each THREAD within the current BLOCK
            for (int j = 0; j < (blockSize*blockSize); j++){
                //setup the indexes
                pointerToPass[i].blockId = i;
                pointerToPass[i].threadId = j;
                //The third loop, copies over a collection of passwords for each THREAD 
                //within the current BLOCK
                for (int l = 0; l < numEach; l++) {
                    //convert the passwords from string to char[] before adding
                    string tmp = passwords.front();
                    char charTmp[1024];
                    strcpy(charTmp, tmp.c_str());
                    pointerToPass[i].passwords.push_back(charTmp);
                    //now delete the item from passwords that has just been transfered
                    //over to the other list
                    passwords.pop_front();
                }
            }
        }
    }
}
//Now onto the parallel
__device__ bool comparison(indvPasswords *collection, char *password, int *totalThreads)
{
    //return value
    bool val = false;
    //first calculate the block ID
    int currentBlockId = blockIdx.y * gridDim.x + blockIdx.x;
    //calculate the thread ID
    int currentThreadId = currentBlockId * blockDim.y * blockDim.x + threadIdx.y * blockDim.x + threadIdx.x;
    //Now go and find the data required for this thread
    //Get the block
    for (int i = 0; i < (int)totalThreads; i++) {
        if (collection[i].blockId == currentBlockId) {
            //Now check the thread id
            if (collection[i].threadId == currentThreadId) {
                //Now begin comparison
                for (int j = 0; j < collection[i].passwords.size(); j++)
                {
                    if (password == collection[i].passwords.front()) {
                        //password found!
                        val = true;
                        break;
                    }
                    //delete the recently compared password
                    collection[i].passwords.pop_front();
                }
            }
        }
    }
    return val;
}
__global__ void kernelComp(indvPasswords *collection, char *password, int *totalThreads)
{
    comparison(collection, password, totalThreads);
}
int main()
{
    int size = totalNumThreads;
    //grid and block sizes
    dim3 gridDim(gridSize, gridSize, 1);
    dim3 blockDim(blockSize, blockSize, 1);
    //Get the password
    string tmp = passwordFile();
    //convert 
    char pwd[1024];
    strcpy(pwd, tmp.c_str());
    indexing();
    //device memory pointers
    indvPasswords* array_d;
    char *pwd_d;
    int *threadSize_d;
    int *threads = &totalNumThreads;
    //allocate host memory
    pwd_d = (char*)malloc(1024);


    //allocate memory
    cudaMalloc((void**)&array_d, size);
    cudaMalloc((void**)&pwd_d, 1024);
    cudaMalloc((void**)&threadSize_d, sizeof(int));
    //copy the data to the device
    cudaMemcpy(array_d, pointerToPass, size, cudaMemcpyHostToDevice);
    cudaMemcpy(pwd_d, pwd, 1024, cudaMemcpyHostToDevice);
    cudaMemcpy(threadSize_d, threads, sizeof(int), cudaMemcpyHostToDevice);
    //call the kernel
    kernelComp << <gridDim, blockDim>> >(array_d,pwd_d,threadSize_d);
    //copy results over
    return 0;
}
  1. 当我使用nvcc-std=c+=11编译器开关在linux上编译您的代码时,我会收到以下警告:

    for (int i = 0; i < (int)totalThreads; i++) {
    

    在您的comparison函数中。假定totalThreads是传递给函数的指针:

    __device__ bool comparison(indvPasswords *collection, char *password, int *totalThreads)
    

    几乎可以肯定,这种用法已经被打破了。我很确定这个警告不应该被忽视,你真正想要的是:

    for (int i = 0; i < *totalThreads; i++) {
    
  2. 我得到的唯一错误是在这条线上:

    pointerToPass[i].passwords.push_back(charTmp);
    

    但这似乎并不是你报告的错误:

    $ nvcc -std=c++11 -o t1016 t1016.cu
    /usr/include/c++/4.8.3/bits/stl_list.h(114): error: a value of type "const char *" cannot be used to initialize an entity of type "char [1024]"
          detected during:
            instantiation of "std::_List_node<_Tp>::_List_node(_Args &&...) [with _Tp=char [1024], _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
    /usr/include/c++/4.8.3/ext/new_allocator.h(120): here
            instantiation of "void __gnu_cxx::new_allocator<_Tp>::construct(_Up *, _Args &&...) [with _Tp=std::_List_node<char [1024]>, _Up=std::_List_node<char [1024]>, _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
    (506): here
            instantiation of "std::list<_Tp, _Alloc>::_Node *std::list<_Tp, _Alloc>::_M_create_node(_Args &&...) [with _Tp=char [1024], _Alloc=std::allocator<char [1024]>, _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
    (1561): here
            instantiation of "void std::list<_Tp, _Alloc>::_M_insert(std::list<_Tp, _Alloc>::iterator, _Args &&...) [with _Tp=char [1024], _Alloc=std::allocator<char [1024]>, _Args=<const std::list<char [1024], std::allocator<char [1024]>>::value_type &>]"
    (1016): here
            instantiation of "void std::list<_Tp, _Alloc>::push_back(const std::list<_Tp, _Alloc>::value_type &) [with _Tp=char [1024], _Alloc=std::allocator<char [1024]>]"
    t1016.cu(108): here
    1 error detected in the compilation of "/tmp/tmpxft_0000182c_00000000-8_t1016.cpp1.ii".
    

    这个问题的解决方案可能是不使用数组作为列表元素类型,正如@ManosNikolaidis已经建议的那样。

  3. 然而,我在您的代码中看到的一个更大的问题是,您试图在__device__函数中使用c++标准库中的项,但这不起作用:

    struct indvPasswords
    {
        int blockId;
        int threadId;
        list<char[1024]> passwords;  // using std::list
    };
    ...
    __global__ void kernelComp(indvPasswords *collection, char *password, int *totalThreads)
                               ^^^^^^^^^^^^^
                // can't use std::list in device code
    

    您应该重写设备使用的数据结构,使其仅依赖于内置类型或从这些内置类型派生的类型。

这一行有一个问题:

list<char[1024]> passwords;

数组不能在STL容器中使用,因为它要求类型是可复制构造的和可赋值的。更多详细信息请点击此处。尝试对每个密码使用std::string。甚至是array<char, 1024>

您实际上是在使用new在这里创建一个数组

indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];

但我认为没有任何问题