在GPU上使用CUDA生成笛卡尔积

在GPU上使用CUDA生成笛卡尔积,cuda,gpu,numerical-methods,cartesian,Cuda,Gpu,Numerical Methods,Cartesian,我想知道在GPU上使用CUDA生成笛卡尔积的方法。 简单案例: 我们有两份清单: A = {0.0, 0.1, 0.2} B = {0.0, 0.1, 0.2} A x B = C = { {0.0, 0.0}, {0.0, 0.1}, {0.0, 0.2}, {0.1, 0.0}, {0.1, 0.1} ...} 如何在GPU中生成(列表列表)C?如何对每个列表都有M个值的N个列表执行此操作 我使用的术语可能不正确。我可以试着解释我的意思: 我实际上是在尝试生成一个真值表:一个二进制

我想知道在GPU上使用CUDA生成笛卡尔积的方法。
简单案例: 我们有两份清单:

 A = {0.0, 0.1, 0.2}   B = {0.0, 0.1, 0.2}
 A x B = C = { {0.0, 0.0}, {0.0, 0.1}, {0.0, 0.2}, {0.1, 0.0}, {0.1, 0.1} ...}
如何在GPU中生成(列表列表)C?如何对每个列表都有M个值的N个列表执行此操作

我使用的术语可能不正确。我可以试着解释我的意思:
我实际上是在尝试生成一个真值表:一个二进制真值表

二元真值表如下所示

A     B
0     0
0     1
1     0
1     1
其中A有两个值{0,1},B有{0,1}。在我的例子中,A和B有两个以上的值,首先是31个值(0-30)。对于集合A中的每个值,集合B中有31个值,我需要枚举它们并将它们存储在内存中


除此之外,我需要将算法扩展到N个列表,而不是2个列表(A和B)

我不认为这是有效的;只是功能性的:

#include <thrust/device_vector.h>
#include <thrust/pair.h>
#include <thrust/copy.h>
#include <iterator>

__global__ void cartesian_product(const int *a, size_t a_size,
                                  const int *b, size_t b_size,
                                  thrust::pair<int,int> *c)
{
  unsigned int idx = blockIdx.x * blockDim.x + threadIdx.x;

  if(idx < a_size * b_size)
  {
    unsigned int a_idx = idx / a_size;
    unsigned int b_idx = idx % a_size;

    c[idx] = thrust::make_pair(a[a_idx], b[b_idx]);
  }
}

int main()
{
  thrust::device_vector<int> a(3);
  a[0] = 0; a[1] = 1; a[2] = 2;

  thrust::device_vector<int> b(3);
  b[0] = 0; b[1] = 1; b[2] = 2;

  thrust::device_vector<thrust::pair<int,int> > c(a.size() * b.size());

  unsigned int block_size = 256;
  unsigned int num_blocks = (c.size() + (block_size - 1)) / block_size;

  cartesian_product<<<num_blocks, block_size>>>(thrust::raw_pointer_cast(a.data()), a.size(),
                                                thrust::raw_pointer_cast(b.data()), b.size(),
                                                thrust::raw_pointer_cast(c.data()));

  std::cout << "a: { ";
  thrust::copy(a.begin(), a.end(), std::ostream_iterator<int>(std::cout, ", "));
  std::cout << "}" << std::endl;

  std::cout << "b: { ";
  thrust::copy(b.begin(), b.end(), std::ostream_iterator<int>(std::cout, ", "));
  std::cout << "}" << std::endl;

  std::cout << "c: { ";
  for(unsigned int i = 0; i < c.size(); ++i)
  {
    thrust::pair<int,int> x = c[i];
    std::cout << "(" << x.first << ", " << x.second << "), ";
  }
  std::cout << "}" << std::endl;

  return 0;
}

你试过什么吗?在CPU上生成笛卡尔积,只需通过迭代器或向量向量即可。但我看不出有任何想法,如何在GPU中实现这一点。我想做一个柜台;将一个添加到最低有效数组索引,并将溢出向左移动。但这也是不可能实现的(至少对我来说是GPU上的),我熟悉的2个集合产生了一组有序对。您使用什么规则从两个集合创建一组三元组?这是一个家庭作业问题吗?开始思考如何在GPU上并行解决问题的一个有用的启发方法是提出线程策略。每条线都会做什么?在产生大量输出数据点的算法中(比如这一个),一个常见的线程策略是让每个线程负责产生一个输出点(假设我有两个集合的情况下是有序对)。如果集合A的大小是A,集合B的大小是B,那么我知道我需要A*B线程。一个2D线程数组立即浮现在我的脑海中,每个线程将从2个输入集合中选择一个元素。感谢你的回答,它至少给了我并行思考的起点。不,这不是家庭作业。关于笛卡尔积,你是对的。我已经纠正了我在这个问题上的错误。在我的实际问题中,我至少有3个列表,所以我在写下这个问题的时候被冲昏头脑了。如果我看到2个列表是如何工作的,也许我可以考虑如何扩展它。谢谢Jared。这确实是我所希望的最干净的方法。再次感谢。
$ nvcc cartesian_product.cu -run
a: { 0, 1, 2, }
b: { 0, 1, 2, }
c: { (0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), }