CUDA,可能没有为数组指定新的初始值设定项

时间:2015-12-30 17:23:08

标签: c++ cuda

所以我目前有这个代码,但是我在编译时遇到错误,“可能没有为数组指定新的初始化程序”,但在我的代码中没有声明新数组。所以我不确定这个问题发生在哪里以及如何发生。这是我觉得问题的代码部分....

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;
}

2 个答案:

答案 0 :(得分:1)

这一行存在问题:

list<char[1024]> passwords;

数组不能在STL容器中使用,因为它要求类型是可复制构造和可分配的。更多细节here。尝试为每个密码使用std::string。甚至是array<char, 1024>

您实际上是使用new在此处创建数组

indvPasswords* pointerToPass = new indvPasswords[totalNumThreads];

但是我没有看到任何错误

答案 1 :(得分:1)

  1. 当我使用-std=c+=11 nvcc编译器开关在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".
    

    该问题的解决方案可能是not use an array as the list element type,正如@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
    

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