在Cuda / Thrust中调用所有组合的仿函数

时间:2017-01-22 17:36:37

标签: c++ cuda thrust

我有两个索引集,一个在[0,N]范围内,一个在[0,M]范围内,其中N!= M.索引用于指代不同#include<stdio.h> #include<string.h> int * hexToBin(char plain_Text64[]); char plain_Text64[17]={}; int binary_Plain_Text64[64]={}; int main(){ int *bin; printf("Enter 64bit Plain Text\n"); scanf("%s",plain_Text64); bin=hexToBin(plain_Text64); int i=0; for(i=0;i<64;i++){ //printf("%d\n",*(bin+i)); } printf("%d\n",binary_Plain_Text64[0]); } //Hex Value to Binary int * hexToBin(char plain_Text64[]){ int k; int hexDigitToBinary[16][4] = {{0,0,0,0}, {0,0,0,1}, {0,0,1,0}, {0,0,1,1}, {0,1,0,0}, {0,1,0,1}, {0,1,1,0}, {0,1,1,1}, {1,0,0,0}, {1,0,0,1}, {1,0,1,0}, {1,0,1,1}, {1,1,0,0}, {1,1,0,1}, {1,1,1,0}, {1,1,1,1}}; char hexDigits[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'}; char hexadecimal[17]={}; int i,j,index=0; strcat(hexadecimal,plain_Text64); for(i=0; i<16; i++){ for(j = 0; j < 16; j++){ //printf("%c\t",hexadecimal[i]); //printf("%c\n",hexDigits[j]); if(hexadecimal[i] == hexDigits[j]){ //printf("OK\n"); for(k=0;k<4;k++){ binary_Plain_Text64[index++]= hexDigitToBinary[j][k]; } } } } return binary_Plain_Text64; } 中的值第

基本上,我想为这些索引的每个组合创建一个GPU线程,因此N * M个线程。每个线程都应该根据索引组合计算一个值,并将结果存储在另一个thrust::device_vector中,同时根据输入组合的唯一索引。

这似乎是一个相当标准的问题,但我无法找到一种方法来做到这一点。文档只提到了问题,其中向量的元素i需要用另一个向量的元素i计算某些东西。有thrust::device_vector,但据我所知,它只给了我重新排序数据的选项,我也必须指定顺序。

一些代码:

thrust::permutation_iterator

我相当确定这很容易实现,我想我只是错过了正确的搜索字词。无论如何,所有帮助赞赏:)

1 个答案:

答案 0 :(得分:3)

  1. 大概是在你的仿函数运算符而不是:

        m_result[i + j * m_vec1.size()] = m_vec1[i] + m_vec1[j];
                                               ^           ^
    
    你的意思是:

        m_result[i + j * m_vec1.size()] = m_vec1[i] + m_vec2[j];
                                               ^           ^
    
  2. 我认为可能有很多方法可以解决这个问题,但为了不争论与问题没有密切关系的事情,我会尽量保持尽可能接近你给定的代码。< / p>

  3. 设备代码中无法在向量上执行[]等操作。因此,我们必须将您的仿函数转换为原始数据指针,而不是直接推力矢量操作。

  4. 有了这些警告,以及我们处理您的ij指数的方式稍作修改,我认为您所要求的并不困难。

    基本策略是按照建议创建长度为N*M的结果向量,然后在仿函数运算符中创建索引ij。在这样做时,我们只需要将一个索引传递给仿函数,例如, thrust::transformthrust::for_each创建输出:

    $ cat t79.cu
    #include <thrust/device_vector.h>
    #include <thrust/host_vector.h>
    #include <thrust/for_each.h>
    #include <thrust/iterator/counting_iterator.h>
    #include <thrust/execution_policy.h>
    #include <iostream>
    
        struct myFunctor
        {
            const int *m_vec1;
            const int *m_vec2;
            int *m_result;
            size_t v1size;
            myFunctor(thrust::device_vector<int> const& vec1, thrust::device_vector<int> const& vec2, thrust::device_vector<int>& result)
            {
              m_vec1 = thrust::raw_pointer_cast(vec1.data());
              m_vec2 = thrust::raw_pointer_cast(vec2.data());
              m_result = thrust::raw_pointer_cast(result.data());
              v1size = vec1.size();
            }
    
            __host__ __device__
            void operator()(const size_t  x) const
            {
                size_t i = x%v1size;
                size_t j = x/v1size;
                m_result[i + j * v1size] = m_vec1[i] + m_vec2[j];
            }
        };
    
    int main()
    {
        // Initialize some data
        const int N = 2;
        const int M = 3;
        thrust::host_vector<int> vec1_host(N);
        thrust::host_vector<int> vec2_host(M);
        vec1_host[0] = 1;
        vec1_host[1] = 5;
        vec2_host[0] = -3;
        vec2_host[1] = 42;
        vec2_host[2] = 9;
    
        // Copy to device
        thrust::device_vector<int> vec1_dev = vec1_host;
        thrust::device_vector<int> vec2_dev = vec2_host;
    
        // Allocate device memory to copy results to
        thrust::device_vector<int> result_dev(vec1_host.size() * vec2_host.size());
    
        // How do I create N*M threads, each of which calls func(i, j) ?
        thrust::for_each_n(thrust::device, thrust::counting_iterator<size_t>(0), (N*M), myFunctor(vec1_dev, vec2_dev, result_dev));
        // Copy results back
        thrust::host_vector<int> result_host = result_dev;
        for(int i : result_host)
            std::cout << i << ", ";
        std::cout << std::endl;
        // Expected output:
        // -2, 2, 43, 47, 10, 14
        return 0;
    }
    $ nvcc -std=c++11 -arch=sm_61 -o t79 t79.cu
    $ ./t79
    -2, 2, 43, 47, 10, 14,
    $
    

    回想起来,我认为这或多或少正是@ eg0x20所暗示的。