Matrix 多个小矩阵的固定向量并行乘法
情况如下:我有许多(1000个)元素,这些元素由尺寸为4x2、9x3的小矩阵给出。。。你明白了。所有矩阵都有相同的维数 我想用一个预先计算的固定向量乘以这些矩阵中的每一个。简言之:Matrix 多个小矩阵的固定向量并行乘法,matrix,cuda,parallel-processing,thrust,Matrix,Cuda,Parallel Processing,Thrust,情况如下:我有许多(1000个)元素,这些元素由尺寸为4x2、9x3的小矩阵给出。。。你明白了。所有矩阵都有相同的维数 我想用一个预先计算的固定向量乘以这些矩阵中的每一个。简言之: for(i = 1...n) X[i] = M[i] . N; 使用推力并行执行此操作的最佳方法是什么?如何在内存中布局数据 注意:可能会有专门的、更合适的库在GPU上执行此操作。我对推力感兴趣,因为它允许我部署到不同的后端,而不仅仅是CUDA。一种可能的方法: 将数组(矩阵)展平为单个数据向量。无论如何,
for(i = 1...n)
X[i] = M[i] . N;
使用推力并行执行此操作的最佳方法是什么?如何在内存中布局数据
注意:可能会有专门的、更合适的库在GPU上执行此操作。我对推力感兴趣,因为它允许我部署到不同的后端,而不仅仅是CUDA。一种可能的方法:
#include <iostream>
#include <stdlib.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/functional.h>
#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/transform.h>
#define N_MAT 1000
#define H_MAT 4
#define W_MAT 3
#define RANGE 1024
struct my_modulo_functor : public thrust::unary_function<int, int>
{
__host__ __device__
int operator() (int idx) {
return idx%(H_MAT*W_MAT);}
};
int main(){
thrust::host_vector<int> data(N_MAT*H_MAT*W_MAT);
thrust::host_vector<int> scale(H_MAT*W_MAT);
// synthetic; instead flatten/copy matrices into data vector
for (int i = 0; i < N_MAT*H_MAT*W_MAT; i++) data[i] = rand()%RANGE;
for (int i = 0; i < H_MAT*W_MAT; i++) scale[i] = rand()%RANGE;
thrust::device_vector<int> d_data = data;
thrust::device_vector<int> d_scale = scale;
thrust::device_vector<int> d_result(N_MAT*H_MAT*W_MAT);
thrust::transform(d_data.begin(), d_data.end(), thrust::make_permutation_iterator(d_scale.begin(), thrust::make_transform_iterator(thrust::counting_iterator<int>(0), my_modulo_functor())) ,d_result.begin(), thrust::multiplies<int>());
thrust::host_vector<int> result = d_result;
for (int i = 0; i < N_MAT*H_MAT*W_MAT; i++)
if (result[i] != data[i] * scale[i%(H_MAT*W_MAT)]) {std::cout << "Mismatch at: " << i << " cpu result: " << (data[i] * scale[i%(H_MAT*W_MAT)]) << " gpu result: " << result[i] << std::endl; return 1;}
std::cout << "Success!" << std::endl;
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义N_MAT 1000
#定义H_MAT 4
#定义W_MAT 3
#定义范围1024
结构my_模函数:公共推力::一元函数
{
__主机设备__
int运算符()(int idx){
返回idx%(H_MAT*W_MAT);}
};
int main(){
推力::主机向量数据(N_-MAT*H_-MAT*W_-MAT);
推力:主矢量标度(H_-MAT*W_-MAT);
//合成;而是将矩阵展平/复制到数据向量中
对于(int i=0;i 如果(result[i]!=data[i]*scale[i%(H_MAT*W_MAT)]{std::cout在寻找一个简单的用于乘法小矩阵的软件库时,您可以查看一下。下面,代码根据典型的GEMM参数请求一个专门的矩阵内核(请注意,有些适用)
给定上面的代码,您可以继续运行“xmm”,对整个系列(小)矩阵运行“xmm”,而无需特定的数据结构(下面的代码也使用“预取位置”)
如果(0
除了如上所示的手动循环控制之外,还可以使用libxsmm_gemm_batch(或libxsmm_gemm_batch_omp)(请参阅)。如果存在描述操作数系列(A、B和C矩阵)的数据结构,则后者非常有用
此库提供优异性能的原因有两个:(1)使用内存中代码生成技术进行动态代码专门化;(2)在计算当前乘积时加载下一个矩阵操作数
(如果您正在寻找能够与C/C++很好地融合的东西,这个库支持它。但是,它并不针对CUDA/推力。)这似乎是一个不错的方法。关于使用花式迭代器而不是更保守的方法所带来的开销,你有什么想法吗?更保守的方法的特点是什么?你是说使用跨步范围方法来创建一个完整的标度向量吗?我很好奇变换(数字,迭代器)的开销有多大
操作引入了标准的转换(数字、其他数字)
操作。
double alpha = 1, beta = 1;
const char transa = 'N', transb = 'N';
int flags = LIBXSMM_GEMM_FLAGS(transa, transb);
int prefetch = LIBXSMM_PREFETCH_AUTO;
libxsmm_blasint m = 23, n = 23, k = 23;
libxsmm_dmmfunction xmm = NULL;
xmm = libxsmm_dmmdispatch(m, n, k,
&m/*lda*/, &k/*ldb*/, &m/*ldc*/,
&alpha, &beta, &flags, &prefetch);
if (0 < n) { /* check that n is at least 1 */
# pragma parallel omp private(i)
for (i = 0; i < (n - 1); ++i) {
const double *const ai = a + i * asize;
const double *const bi = b + i * bsize;
double *const ci = c + i * csize;
xmm(ai, bi, ci, ai + asize, bi + bsize, ci + csize);
}
xmm(a + (n - 1) * asize, b + (n - 1) * bsize, c + (n - 1) * csize,
/* pseudo prefetch for last element of batch (avoids page fault) */
a + (n - 1) * asize, b + (n - 1) * bsize, c + (n - 1) * csize);
}