- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我目前正尝试在我的 GPU 上使用 CUBLAS 实现矩阵乘法。
它适用于方矩阵和特定大小的输入,但对于其他输入,最后一行不会返回(并且包含 0,因为这是我实现它的方式)。
我认为这是 cublasSgemm
的分配或语法问题,但我找不到它在哪里。
注意:如果您不熟悉 CUBLAS:它是 column-majored ,这就是为什么看起来操作是以另一种方式执行的。
如有任何帮助,我们将不胜感激。
请注意,gpuErrchk
和 cublasErrchk
当然与此处无关。
#include <cuda.h>
#include <cuda_runtime.h>
#include <cublas_v2.h>
#include <vector>
std::vector<float> CUDA_mult_MAT(const std::vector<float> &data_1 , const uint64_t data_1_rows, const uint64_t data_1_columns,
const std::vector<float> &data_2 , const uint64_t data_2_rows, const uint64_t data_2_columns){
cublasHandle_t handle;
cublasErrchk(cublasCreate(&handle));
std::vector<float> result(data_1_rows * data_2_columns); //Vector holding the result of the multiplication
/*----------------------------------------------------------------------------------------------*/
float* GPU_data_1 = NULL;
gpuErrchk(cudaMalloc((void**)&GPU_data_1 , data_1.size()*sizeof(float))); //Allocate memory on the GPU
gpuErrchk(cudaMemcpy(GPU_data_1, data_1.data(), data_1.size()*sizeof(float), cudaMemcpyHostToDevice)); //Copy data from data_1 to GPU_data_1
float* GPU_data_2 = NULL;
gpuErrchk(cudaMalloc((void**)&GPU_data_2 ,data_2.size()*sizeof(float))); //Allocate memory on the GPU
gpuErrchk(cudaMemcpy(GPU_data_2, data_2.data(), data_2.size()*sizeof(float), cudaMemcpyHostToDevice));//Copy data from data_2 to GPU_data_2
float* GPU_result = NULL;
gpuErrchk(cudaMalloc((void**)&GPU_result , result.size()*sizeof(float))); //Allocate memory on the GPU
/*----------------------------------------------------------------------------------------------*/
const float alpha = 1.f;
const float beta = 0.f;
cublasErrchk(
cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
data_2_columns , data_2_rows ,data_1_columns,
&alpha , GPU_data_2 , data_2_columns,
GPU_data_1 , data_1_columns,
&beta , GPU_result , data_1_rows)
); //Perform multiplication
gpuErrchk(cudaMemcpy(result.data() , GPU_result , result.size() * sizeof(float) , cudaMemcpyDeviceToHost)); //Copy back to the vector 'result'
gpuErrchk(cudaFree(GPU_data_1)); //Free GPU memory
gpuErrchk(cudaFree(GPU_data_2)); //Free GPU memory
gpuErrchk(cudaFree(GPU_result)); //Free GPU memory
cublasErrchk(cublasDestroy_v2(handle));
return result;
}
#include <iostream>
#include <vector>
int main(){
const std::vector<float> r1 = CUDA_mult_MAT({1 , 2 , 3 , 4 , 5 , 6} , 2 , 3 ,
{7 , 8 , 9 , 10 , 11 , 12} , 3 , 2);
/*
Product :
7 8
1 2 3 9 10
4 5 6 11 12
*/
for(auto & value: r1){std::cout << value << " " ;}
std::cout << std::endl;
const std::vector<float> r2 = CUDA_mult_MAT({7 , 8 , 9 , 10 , 11 , 12} , 3 , 2 ,
{1 , 2 , 3 , 4 , 5 , 6} , 2 , 3);
/*
Product :
7 8
9 10 1 2 3
11 12 4 5 6
*/
for(auto & value: r2){std::cout << value << " " ;}
std::cout << std::endl;
return 0;
}
58 64 139 154
39 54 69 49 68 87 0 0 0
^~~~~~~
58 64 139 154
39 54 69 49 68 87 59 82 105
^~~~~~~
最佳答案
我们可以通过不同方式观察您的 CUBLAS 使用问题。
首先,研究CUBLAS Sgemm documentation ,我们看到 3 个参数 m
、n
、k
出现,按此顺序紧接在转置说明符之后:
cublasStatus_t cublasSgemm(cublasHandle_t handle,
cublasOperation_t transa, cublasOperation_t transb,
int m, int n, int k,
^ ^ ^
我们还观察到矩阵维度由下式给出:
A , B and C are matrices stored in column-major format with dimensions op ( A ) m × k , op ( B ) k × n and C m × n ,
所以第一个输入矩阵的维度是 m x k
第二个输入矩阵的维度为 k x n
,输出矩阵的维度为 m x n
让我们暂时关注输出矩阵。鉴于其维度是使用 m
和 n
参数指定的,它不可能是正确的(假设在非正方形的情况下)传递 only data_2
维度:
cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
data_2_columns , data_2_rows ,data_1_columns,
^^^^^^^^^^^^^^ ^^^^^^^^^^^
其次,从错误检查的角度来看,通过使用 cuda-memcheck
运行您的代码,您可以快速估计您的 CUBLAS 调用有问题。报告的第一个错误如下:
$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
========= Invalid __global__ read of size 4
========= at 0x000006f0 in void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>)
========= by thread (64,0,0) in block (0,0,0)
========= Address 0x7f9c30a2061c is out of bounds
========= Device Frame:void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>) (void gemmSN_NN_kernel<float, int=256, int=4, int=2, int=8, int=3, int=4, bool=0, cublasGemvTensorStridedBatched<float const >, cublasGemvTensorStridedBatched<float>>(cublasGemmSmallNParams<float const , cublasGemvTensorStridedBatched<float const >, float>) : 0x6f0)
========= Saved host backtrace up to driver entry point at kernel launch time
========= Host Frame:/usr/lib/x86_64-linux-gnu/libcuda.so.1 (cuLaunchKernel + 0x2b8) [0x1e5cc8]
========= Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x1063c8b]
========= Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x10a9965]
========= Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x6bfacc]
========= Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x5fc7af]
========= Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 [0x436c35]
========= Host Frame:/usr/local/cuda/lib64/libcublasLt.so.11 (cublasLtMatmul + 0x60f) [0x43484f]
========= Host Frame:/usr/local/cuda/lib64/libcublas.so.11 [0x9ef6db]
========= Host Frame:/usr/local/cuda/lib64/libcublas.so.11 [0x50e4f0]
========= Host Frame:/usr/local/cuda/lib64/libcublas.so.11 (cublasSgemm_v2 + 0x1ee) [0x50f29e]
========= Host Frame:./t23 [0x7986]
========= Host Frame:./t23 [0x7b4c]
========= Host Frame:/lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main + 0xe7) [0x21b97]
========= Host Frame:./t23 [0x744a]
=========
当然,一种可能的解决方案是转置输入矩阵,因此它们按列主要顺序排列,CUBLAS 提供了带有 Sgemm
的选项来执行此操作(见上文)。但是在我看来,您要做的是在不转置输入数组的情况下进行 C 风格的行主乘法。有文章here其中描述了如何做到这一点。
当我将该启发式应用于您的 cublasSgemm()
调用时,我得到了:
cublasSgemm(handle , CUBLAS_OP_N , CUBLAS_OP_N,
data_2_columns , data_1_rows ,data_1_columns,
&alpha , GPU_data_2 , data_2_columns,
GPU_data_1 , data_1_columns,
&beta , GPU_result , data_2_columns)
当我使用这些更改编译并运行您的代码时,我得到:
$ cuda-memcheck ./t23
========= CUDA-MEMCHECK
58 64 139 154
39 54 69 49 68 87 59 82 105
========= ERROR SUMMARY: 0 errors
关于c++ - CUBLAS 矩阵乘法与行主数据无转置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64847728/
猫f1.txt阿曼维沙尔阿杰贾伊维杰拉胡尔曼尼什肖比特批评塔夫林现在输出应该符合上面给定的条件 最佳答案 您可以在文件读取循环中设置一个计数器并打印它, 计数=0 读取行时做 让我们数一数++ if
我正在尝试查找文件 1 和文件 2 中的共同行。如果公共(public)行存在,我想写入文件 2 中的行,否则打印文件 1 中的非公共(public)行。fin1 和 fin2 是这里的文件句柄。它读
我有这个 SQL 脚本: CREATE TABLE `table_1` ( `IDTable_1` int(11) NOT NULL, PRIMARY KEY (`IDTable_1`) );
我有 512 行要插入到数据库中。我想知道提交多个插入内容是否比提交一个大插入内容有任何优势。例如 1x 512 行插入 -- INSERT INTO mydb.mytable (id, phonen
如何从用户中选择user_id,SUB(row, row - 1),其中user_id=@userid我的表用户,id 为 1、3、4、10、11、23...(不是++) --id---------u
我曾尝试四处寻找解决此问题的最佳方法,但我找不到此类问题的任何先前示例。 我正在构建一个基于超本地化的互联网购物中心,该区域分为大约 3000 个区域。每个区域包含大约 300 个项目。它们是相似的项
preg_match('|phpVersion = (.*)\n|',$wampConfFileContents,$result); $phpVersion = str_replace('"','',
我正在尝试创建一个正则表达式,使用“搜索并替换全部”删除 200 个 txt 文件的第一行和最后 10 行 我尝试 (\s*^(\h*\S.*)){10} 删除包含的前 10 行空白,但效果不佳。 最
下面的代码从数据库中获取我需要的信息,但没有打印出所有信息。首先,我知道它从表中获取了所有正确的信息,因为我已经在 sql Developer 中尝试过查询。 public static void m
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我试图在两个表中插入记录,但出现异常。您能帮我解决这个问题吗? 首先我尝试了下面的代码。 await _testRepository.InsertAsync(test); await _xyzRepo
这个基本的 bootstrap CSS 显示 1 行 4 列: Text Text Text
如果我想从表中检索前 10 行,我将使用以下代码: SELECT * FROM Persons LIMIT 10 我想知道的是如何检索前 10 个结果之后的 10 个结果。 如果我在下面执行这段代码,
今天我开始使用 JexcelApi 并遇到了这个:当您尝试从特定位置获取元素时,不是像您通常期望的那样使用sheet.getCell(row,col),而是使用sheet.getCell(col,ro
我正在尝试在我的网站上开发一个用户个人资料系统,其中包含用户之前发布的 3 个帖子。我可以让它选择前 3 条记录,但它只会显示其中一条。我是不是因为凌晨 2 点就想编码而变得愚蠢? query($q)
我在互联网上寻找答案,但找不到任何答案。 (我可能问错了?)我有一个看起来像这样的表: 我一直在使用查询: SELECT title, date, SUM(money) FROM payments W
我有以下查询,我想从数据库中获取 100 个项目,但 host_id 多次出现在 urls 表中,我想每个 host_id 从该表中最多获取 10 个唯一行。 select * from urls j
我的数据库表中有超过 500 行具有特定日期。 查询特定日期的行。 select * from msgtable where cdate='18/07/2012' 这将返回 500 行。 如何逐行查询
我想使用 sed 从某一行开始打印 n 行、跳过 n 行、打印 n 行等,直到文本文件结束。例如在第 4 行声明,打印 5-9,跳过 10-14,打印 15-19 等 来自文件 1 2 3 4 5 6
我目前正在执行验证过程来检查用户的旧密码,但问题是我无法理解为什么我的查询返回零行,而预期它有 1 行。另一件事是,即使我不将密码文本转换为 md5,哈希密码仍然得到正确的答案,但我不知道为什么会发生
我是一名优秀的程序员,十分优秀!