当前位置: 首页 > news >正文

装修网站怎么做的好电子商务网站建设与管理课后第四章

装修网站怎么做的好,电子商务网站建设与管理课后第四章,网站网站做代理违法吗,android studio官网下载前置准备 安装NVIDIA Nsight Compute。 安装好后选择使用管理员权限启动下载官方 Demo 代码官方博客Shuffle warp 1. 任务介绍及CPU版本 1.1 任务介绍 任务理解: 有一个 L x M 的矩阵 M 1 M_1 M1​ 对其每行取平均值 得到 V 1 ∈ R L 1 V_1 \in \mathbb{R}^{…

前置准备

  • 安装NVIDIA Nsight Compute。 安装好后选择使用管理员权限启动
  • 下载官方 Demo 代码
  • 官方博客
  • Shuffle warp

1. 任务介绍及CPU版本

1.1 任务介绍

在这里插入图片描述
任务理解:

  • 有一个 L x M 的矩阵 M 1 M_1 M1 对其每行取平均值 得到 V 1 ∈ R L × 1 V_1 \in \mathbb{R}^{L \times 1} V1RL×1 的列向量
  • 有一个 L x L 的矩阵 M 2 M_2 M2 V 1 V_1 V1做矩阵乘法,最后得到 V 2 ∈ R L × 1 V_2 \in \mathbb{R}^{L \times 1} V2RL×1 的列向量

1.2 CPU版本实现

/**input: input 矩阵,维度为(N, L, M) N为Batchoutput: ouput 矩阵,维度为(N, L)matrix: matrix 维度为(L, L)
*/
template <typename T>
void cpu_version1(T *input, T *output, T *matrix, int L, int M, int N){
#pragma omp parallel forfor (int k = 0; k < N; k++){      // repeat the following, N timesstd::vector<T> v1(L);           // vector length of Lfor (int i = 0; i < M; i++)     // compute average vector over M input vectorsfor (int j = 0; j < L; j++)v1[j] += input[k*M*L+j*M+i];for (int j = 0; j < L; j++)v1[j] /= M;for (int i = 0; i < L; i++)     // matrix-vector multiplyfor (int j = 0; j < L; j++)output[i*N+k] += matrix[i*L+j]*v1[j];}
}

1.3 计时逻辑

#include <time.h>
#ifdef __linux__
#define USECPSEC 1000000ULL
#include <sys/time.h>
unsigned long long dtime_usec(unsigned long long start){timeval tv;gettimeofday(&tv, 0);return ((tv.tv_sec*USECPSEC)+tv.tv_usec)-start;
}
#elif defined(WIN32)
#include <windows.h>
double dtime_usec(double start) {LARGE_INTEGER frequency;        // ticks per secondLARGE_INTEGER t1;               // ticksdouble elapsedTime;// get ticks per secondQueryPerformanceFrequency(&frequency);// get current timeQueryPerformanceCounter(&t1);// compute the elapsed time in micro-second resolution(毫秒)elapsedTime = (t1.QuadPart - start) * 1000000.0 / frequency.QuadPart;return elapsedTime;
}
#endif

1.4 main函数

typedef double ft;int main(){ft *d_input, *h_input, *d_output, *h_outputc, *h_outputg, *d_matrix, *h_matrix;int L = my_L; int M = my_M; int N = my_N;// host allocationsh_input   = new ft[N*L*M];h_matrix  = new ft[L*L];h_outputg = new ft[N*L];h_outputc = new ft[N*L];// data initializationfor (int i = 0; i < N*L*M; i++) h_input[i] = (rand()&1)+1;  // 1 or 2for (int i = 0; i < L*L; i++) h_matrix[i]  = (rand()&1)+1;  // 1 or 2// create result to test for correctnessLARGE_INTEGER st;double dt;QueryPerformanceCounter(&st);  // 获取起始时间点cpu_version1(h_input, h_outputc, h_matrix, L, M, N);dt = dtime_usec(st.QuadPart);std::cout << "CPU execution time: \t" << dt / 1000.0f << "ms" << std::endl;// device allocationscudaMalloc(&d_input, N*L*M*sizeof(ft));cudaMalloc(&d_output,  N*L*sizeof(ft));cudaMalloc(&d_matrix,  L*L*sizeof(ft));cudaCheckErrors("cudaMalloc failure");// copy input data from host to devicecudaMemcpy(d_input,  h_input,  N*L*M*sizeof(ft), cudaMemcpyHostToDevice);cudaMemcpy(d_matrix, h_matrix,   L*L*sizeof(ft), cudaMemcpyHostToDevice);cudaMemset(d_output, 0, N*L*sizeof(ft));cudaCheckErrors("cudaMemcpy/Memset failure");// run on device and measure execution timeQueryPerformanceCounter(&st);  // 获取起始时间点gpu_version1<<<1, L>>>(d_input, d_output, d_matrix, L, M, N);cudaCheckErrors("kernel launch failure");cudaDeviceSynchronize();cudaCheckErrors("kernel execution failure");dt = dtime_usec(st.QuadPart);cudaMemcpy(h_outputg, d_output, N*L*sizeof(ft), cudaMemcpyDeviceToHost);cudaCheckErrors("cudaMemcpy failure");for (int i = 0; i < N*L; i++) if (h_outputg[i] != h_outputc[i]) {std::cout << "Mismatch at " << i << " was: " << h_outputg[i] << " should be: " << h_outputc[i] << std::endl; return 0;}std::cout << "Kernel execution time: \t" << dt / 1000.0f << "ms" << std::endl;return 0;
}

2. GPU version1

2.1 实现

template<typename T>
__global__ void gpu_version1(const T * __restrict__ input, T * __restrict__ output, const T * __restrict__ matrix,const int L,const int M, const int N
)
{___shared__ T smem[L];int idx = threadIdx.x;// 以此处理N个Batchfor(int k = 0; k < N; i++){T v = 0;for(int i = 0; i < M; ++i){v += input[K * M * L + M * idx + i]}v /= M;for(int row = 0; row < L; ++row) {smem[idx] = v * M[idx * L + row];// 对矩阵乘法求和for(int s = blockDim.x >> 1; s > 0; s >>=1){__syncthreads();if (idx < s) smem[threadIdx.x] += smem[threadIdx.x + s];}if (!threadIdx.x) ouput[i*N + row] = smem[0];}}
}const int L = 512; // maximum 1024
const int M = 512;
const int N = 1024;
// 调用核函数
gpu_version1<<<1, L>>>(d_input, d_output, d_matrix, L, M, N);

2.2 时间对比

CPU execution time:     2764.96ms
Kernel execution time:  1508.34ms

2.3 Nsight 分析

在这里插入图片描述

可以看到,这里This kernel grid is too small to fill the available resources on this device, resulting in only 0.0 full waves across all SMs.这里说我们的 grid size 设置得太小了,没有充分利用SM。下一版我们增大 Graid size

3. 增加GridSize

3.1 实现

分析上一个核函数调用:

gpu_version1<<<1, L>>>(d_input, d_output, d_matrix, L, M, N);

这里grid size是1,这里可以考虑把这个设置为 Batch size 即 N

gpu_version1<<<N, L>>>(d_input, d_output, d_matrix, L, M, N);

对应得核函数修改, 其实就是 把k 替换成了 blockIdx.x

template <typename T>
__global__ void gpu_version2(const T* __restrict__ input, T* __restrict__ output, const T* __restrict__ matrix, const int L, const int M, const int N) {// parallelize threadIdx.x over vector length, and blockIdx.x across k (N)__shared__ T smem[my_L];int idx = threadIdx.x;int k = blockIdx.x;T v1 = 0;for (int i = 0; i < M; i++)v1 += input[k * M * L + idx * M + i];v1 /= M;for (int i = 0; i < L; i++) {__syncthreads();smem[threadIdx.x] = v1 * matrix[i * L + idx];for (int s = blockDim.x >> 1; s > 0; s >>= 1) {__syncthreads();if (threadIdx.x < s) smem[threadIdx.x] += smem[threadIdx.x + s];}if (!threadIdx.x) output[k + i * N] = smem[0];}
}

3.2 时间对比

CPU execution time:     	3219.04ms
Kernel execution timev1:  	1508.34ms
Kernel execution timev2:  	91.4291ms

可以看到相对v1 提高了15倍 +

3.3 Nsight 分析

3.3.1 概览

相比上一个版本,SM和memory的利用率明显提高了。

在这里插入图片描述

3.3.2 Memoy Workload Analysis

The memory access pattern for global loads in L1TEX might not be optimal. On average, this kernel accesses 8.0 bytes per thread per memory request; but the address pattern, possibly caused by the stride between threads, results in 20.0 sectors per request, or 20.032 = 639.3 bytes of cache data transfers per request. The optimal thread address pattern for 8.0 byte accesses would result in 8.032 = 256.0 bytes of cache data transfers per request, to maximize L1TEX cache performance. Check the  Source Counters section for uncoalesced global loads.
在 L1TEX中,全局加载的内存访问模式可能不是最优的。平均来说,这个kernel 每个线程每次内存请内存会访问8 字节,但是当前的地址模式,可能由于线程之间的跨度导致每次请求了20个 sectors, 每次请求的缓存传输为 20 * 32 = 649.3 字节。对于8字节的访问,最优的线程地址模式使用的缓存传输数据为 8 * 32 = 256字节,为了最大化L1TEX缓存性能,检查没有 coalesed (合并)访问的全局加载。

为什么会导致这么高 ? 可以通过 source页面

在这里插入图片描述
可以发现高亮的这一句进行了大量的L2 Cache访问操作,为什么这一句会导致访问不合并呢?
是因为每次for循环都隔了 idx * M 个数据,导致缓存失效,如何解决这个问题呢?看下一节

http://www.sczhlp.com/news/56979/

相关文章:

  • 北京定制网站价格电商运营网站设计
  • 网站域名做哪个会计科目女生喜欢的100种迷你小手工
  • 做高仿表网站如何编辑网站内容
  • 企业要建设一个网站需要多少钱建设视频网站多少钱
  • 河南高端网站建设公司动漫与游戏制作这个专业怎么样
  • 蓝色通用营销型企业网站模板邯郸网站优化怎么用
  • 站酷设计网站首页竞价推广培训
  • 帝国网站seo建站软件怎么免费升级
  • 网站备案 域名备案做直播教程的网站
  • 怎么检查网站有没有做跳转在线视频网站a一级爰a做免费
  • 国内公关公司排名济南网站优化分析
  • 国外专门用于做网站图片的免费个人简历模板网站
  • 黄金网站软件app大全下载网络营销方案制定
  • 学院网站群建设wordpress邮件发送功能无法开启
  • 烟台做网站焦作网站开发公司
  • 外国好的设计网站大全免费服务器推荐
  • 济宁网站建设优惠seo关键词优化怎么收费
  • 建设公司的网站制作网页设计制作公司做什么
  • 回调函数
  • 2025-09-01 日常生活实用技巧大全(deepseek)
  • 淮北招聘网淮北论坛军刀seo
  • 广西建设网桂建云系统7个湖北seo网站推广策略
  • 做户型图的网站wordpress org
  • 网站上线前应该备案吗如何快速找到公司网站
  • NoSQL-Redis - *--_
  • 团购网站怎么推广WordPress的简约博客主题
  • 爱站网在线全集私人影视wordpress 存储空间
  • 500亿网站建设wordpress 主题 排行榜
  • 类似视频教程网站的wordpress主题芜湖灵创网站建设
  • 快速的网站设计制作酷炫网站