CUDA编程 - 用向量化访存优化 elementwise 核函数 - 学习记录

Cuda elementwise

  • 一、简介
    • 1.1、ElementWise
    • 1.2、 float4 - 向量化访存
  • 二、实践
    • 2.1、如何使用向量化访存
    • 2.2、Cuda elementwise - Add
    • 2.3、Cuda elementwise - Sigmoid
      • 2.3.1、简单的 Sigmoid 函数
      • 2.3.2、ElementWise Sigmoid+ float4(向量化访存)
    • 2.4、Cuda elementwise - relu
      • 2.3.1、简单的 relu 函数
      • 2.3.2、ElementWise relu + float4(向量化访存)
  • 三、不能使用向量化访存的情况
    • Cuda elementwise - Histogram(直方图)
  • 四、完整代码
    • 4.1、sigmoid.cu
    • 4.2、relu.cu
  • 4.3、histogram.cu

一、简介

1.1、ElementWise

Element-wise操作是最基础,最简单的一种核函数的类型,它的计算特点很符合GPU的工作方式:对于每个元素单独做一个算术操作,然后直接输出。虽然简单,但深度学习领域,有很多算子都是这个类型。常见的有Add,Mul,Concat,各种激活Sigmoid,Relu及它们的变体,归一化里的BatchNorm都属于这个类型。

1.2、 float4 - 向量化访存

所谓向量化访存,就是一次性读 4 个 float,而不是单单 1 个

要点:

  • 小数据规模情况下,可以不考虑向量化访存的优化方式
  • 大规模数据情况下,考虑使用向量化访存,且 最好是缩小grid的维度为原来的1/4,避免影响Occupancy
  • float4 向量化访存只对数据规模大的时候有加速效果,数据规模小的时候没有加速效果

float4 的性能提升主要在于访存指令减少了(同样的数据规模,以前需要4条指令,现在只需1/4的指令),指令cache里就能存下更多指令,提高指令cache的命中率。

判断是否用上了向量化访存,是在 nsight compute 看生成的SASS代码里会有没有 LDG.E.128 Rx, [Rx.64]或 STG.E.128 [R6.64], Rx这些指令的存在。有则向量化成功,没有则向量化失败。

在这里插入图片描述

官方参考链接1
官方参考链接2

二、实践

2.1、如何使用向量化访存

c :

#define FLOAT4(value)  *(float4*)(&(value))

宏解释:

对于一个值,先对他取地址,然后再把这个地址解释成 float4
对于这个 float4的指针,对它再取一个值
这样编译器就可以一次读四个 float

c++ :

#define FLOAT4(value) (reinterpret_cast<float4*>(&(value))[0])

将核函数写成 float4 的形式的时候,首先要先使用宏定义,其次要注意线程数的变化。

线程数变化原因:因为一个线程可以处理 4个float了,所以要减少 四倍的线程。 (具体看下面的例子)

2.2、Cuda elementwise - Add

参考链接

2.3、Cuda elementwise - Sigmoid

2.3.1、简单的 Sigmoid 函数

a: Nx1, b: Nx1, c: Nx1, c = sigmoid(a, b)

//sigmoid<<<CeilDiv(N, block_size), block_size>>>(d_A, d_B, N)
//
__global__ void sigmoid(float* x, float* y, int N) {int idx = blockIdx.x * blockDim.x + threadIdx.x;if (idx < N) y[idx] = 1.0f / (1.0f + expf(-x[idx]));
}

2.3.2、ElementWise Sigmoid+ float4(向量化访存)

Sigmoid x: N, y: N y=1/(1+exp(-x)) float4

__global__ void sigmoid_vec4(float4* x, float4* y, int N) {int idx = (blockIdx.x * blockDim.x + threadIdx.x) * 4;if (idx < N) {float4 tmp_x = FLOAT4(x[idx]);float4 tmp_y;tmp_y.x = 1.0f / (1.0f + expf(-tmp_x.x));tmp_y.y = 1.0f / (1.0f + expf(-tmp_x.y));tmp_y.z = 1.0f / (1.0f + expf(-tmp_x.z));tmp_y.w = 1.0f / (1.0f + expf(-tmp_x.w));FLOAT4(y[idx]) = tmp_y;}
}

2.4、Cuda elementwise - relu

2.3.1、简单的 relu 函数

Relu x: N, y: N y=max(0,x)

__global__ void relu(float* x, float* y, int N) {int idx = blockIdx.x * blockDim.x + threadIdx.x;if (idx < N) y[idx] = fmaxf(0.0f, x[idx]);
}

2.3.2、ElementWise relu + float4(向量化访存)

Relu x: N, y: N y=max(0,x) float4

__global__ void relu_float4(float* x, float* y, int N) {int idx = (blockIdx.x * blockDim.x + threadIdx.x) * 4;if (idx < N) {float4 tmp_x = FLOAT4(x[idx]);float4 tmp_y;tmp_y.x = fmaxf(0.0f, tmp_x.x);tmp_y.y = fmaxf(0.0f, tmp_x.y);tmp_y.z = fmaxf(0.0f, tmp_x.z);tmp_y.w = fmaxf(0.0f, tmp_x.w);FLOAT4(y[idx]) = tmp_y;}
}

三、不能使用向量化访存的情况

Cuda elementwise - Histogram(直方图)

x[i] = i-- -- - -- - - -
- - - - -

goal: 统计每个元素出现的次数

①、简单的 Histogram函数

x: Nx1, y: count histogram

__global__ void histogram(int* x, int* y, int N) {int idx = blockIdx.x * blockDim.x + threadIdx.x;if (idx < N) atomicAdd(&(y[x[idx]]), 1);
}

其中 int atomicAdd(int* address, int val);

1、atomicAdd 是 CUDA 中的一个原子加函数,用于实现在多个线程同时修改同一个全局变量的情况下,保证数据一致性和正确性
2、该函数会将原始值和 val 相加,并将结果存储在 address 所指向的内存位置,同时返回原始值
3、当多个线程同时调用 atomicAdd 函数时,CUDA 会自动为它们创建一个硬件级的同步访问机制,从而避免了数据竞争和数据不一致性的问题。

参考链接

②、ElementWise Histogram + float4(向量化访存)

__global__ void histogram_float4(int* x, int* y, int N) {int idx = 4 * (blockIdx.x * blockDim.x + threadIdx.x);if (idx < N) {int4 tmp_y = INT4(x[idx]);atomicAdd(&(y[tmp_y.x]), 1);atomicAdd(&(y[tmp_y.y]), 1);atomicAdd(&(y[tmp_y.z]), 1);atomicAdd(&(y[tmp_y.w]), 1);}
}

运行 histogram_float4 后发现比 histogram 还慢。为什么呢?

1、nvidia 官方回答: Can float4 be used for atomicAdd efficiently?
2、histogram的写入(load)没有向量化指令,只有读取(load)向量化。
3、使用 nsight compute 看生成的SASS,只有 LDG ,没有STG
在这里插入图片描述
4、在一个warp里相邻线程对全局内存y的访问没有合并( 因为在一个warp里面不同线程对全局内存是跳着访问的 )

四、完整代码

4.1、sigmoid.cu

#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <vector>
#include<assert.h>
#include <algorithm>
#include <cublas_v2.h>
#include <cuda_runtime.h>#define FLOAT4(value)  *(float4*)(&(value))#define checkCudaErrors(func)               \
{                                   \cudaError_t e = (func);         \if(e != cudaSuccess)                                        \printf ("%s %d CUDA: %s\n", __FILE__,  __LINE__, cudaGetErrorString(e));        \
}__global__ void relu(float* x, float* y, int N){int idx = blockIdx.x * blockDim.x + threadIdx.x;if(idx < N) y[idx] = fmaxf(0.0f, x[idx]);
}__global__ void relu_float4(float* x, float* y, int N){int idx = (blockIdx.x * blockDim.x + threadIdx.x) * 4;if(idx < N){float4 tmp_x = FLOAT4(x[idx]);float4 tmp_y;tmp_y.x = fmaxf(0.0f, tmp_x.x);tmp_y.y = fmaxf(0.0f, tmp_x.y);tmp_y.z = fmaxf(0.0f, tmp_x.z);tmp_y.w = fmaxf(0.0f, tmp_x.w);FLOAT4(y[idx]) = tmp_y;}
}//nvcc -o sigmoid sigmoid.cu && ./sigmoid
//sigmoid<<<CeilDiv(N, block_size), block_size>>>(d_A, d_B, N)
//a: Nx1, b: Nx1, c: Nx1, c = sigmoid(a, b)
__global__ void sigmoid(float* a, float* b, int N) {int idx = blockIdx.x * blockDim.x + threadIdx.x;if (idx < N) b[idx] = 1.0f / (1.0f + expf(-a[idx]));
}__global__ void sigmoid_float4(float* a, float* b, int N)
{int idx = (blockDim.x * blockIdx.x + threadIdx.x) * 4;if(idx < N){float4 tmp_a = FLOAT4(a[idx]);float4 tmp_b;tmp_b.x = 1.0f /(1.0f + expf(-tmp_a.x));tmp_b.y = 1.0f /(1.0f + expf(-tmp_a.y));tmp_b.z = 1.0f /(1.0f + expf(-tmp_a.z));tmp_b.w = 1.0f /(1.0f + expf(-tmp_a.w));FLOAT4(b[idx]) = tmp_b;}
}template <typename T> 
inline T CeilDiv(const T& a, const T& b) {return (a + b - 1) / b;
}int main(){size_t block_size = 128;size_t N = 1 * 1024;size_t bytes_A = sizeof(float) * N;size_t bytes_B = sizeof(float) * N;float* h_A = (float*)malloc(bytes_A);float* h_B = (float*)malloc(bytes_B);for( int i = 0; i < N; i++ ){h_A[i] = (i / 666) * ((i % 2 == 0) ? 1: -1);}float* d_A;float* d_B;checkCudaErrors(cudaMalloc(&d_A, bytes_A));checkCudaErrors(cudaMalloc(&d_B, bytes_B));checkCudaErrors(cudaMemcpy( d_A, h_A, bytes_A, cudaMemcpyHostToDevice));cudaEvent_t start, stop;checkCudaErrors(cudaEventCreate(&start));checkCudaErrors(cudaEventCreate(&stop));float msec = 0;int iteration = 1000;checkCudaErrors(cudaEventRecord(start));for(int i = 0; i < iteration; i++){//sigmoid<<<CeilDiv(N, block_size), block_size>>>(d_A, d_B, N);//sigmoid_float4<<<CeilDiv(N, block_size), block_size/4>>>(d_A, d_B, N);sigmoid_float4<<<CeilDiv(N/4,block_size), block_size>>>(d_A, d_B, N);}checkCudaErrors(cudaEventRecord(stop));checkCudaErrors(cudaEventSynchronize(stop));checkCudaErrors(cudaEventElapsedTime(&msec, start, stop));printf("sigmoid takes %.3f msec\n", msec/iteration);checkCudaErrors(cudaMemcpy(h_B, d_B, bytes_B, cudaMemcpyDeviceToHost));for(int i = 0; i < N; i++){double err = fabs(h_B[i] - 1.0f/(1.0f + expf(-h_A[i])));if(err > 1.e-6) {printf("wrong answer!\n");break;}}cudaFree(d_A);cudaFree(d_B);free(h_A);free(h_B);return 0;
}

编译和运行代码:

nvcc -o sigmoid sigmoid.cu
./sigmoid 

4.2、relu.cu

#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <vector>
#include<assert.h>
#include <algorithm>
#include <cublas_v2.h>
#include <cuda_runtime.h>#define FLOAT4(value)  *(float4*)(&(value))#define checkCudaErrors(func)               \
{                                   \cudaError_t e = (func);         \if(e != cudaSuccess)                                        \printf ("%s %d CUDA: %s\n", __FILE__,  __LINE__, cudaGetErrorString(e));        \
}//nvcc -o relu relu.cu && ./relu
//sigmoid<<<CeilDiv(N, block_size), block_size>>>(d_A, d_B, N)
//a: Nx1, b: Nx1, c: Nx1, y = relu(x)
__global__ void relu(float* x, float* y, int N){int idx = blockIdx.x * blockDim.x + threadIdx.x;if(idx < N) y[idx] = fmaxf(0.0f, x[idx]);
}__global__ void relu_float4(float* x, float* y, int N){int idx = (blockIdx.x * blockDim.x + threadIdx.x) * 4;if(idx < N){float4 tmp_x = FLOAT4(x[idx]);float4 tmp_y;tmp_y.x = fmaxf(0.0f, tmp_x.x);tmp_y.y = fmaxf(0.0f, tmp_x.y);tmp_y.z = fmaxf(0.0f, tmp_x.z);tmp_y.w = fmaxf(0.0f, tmp_x.w);FLOAT4(y[idx]) = tmp_y;}
}template <typename T> 
inline T CeilDiv(const T& a, const T& b) {return (a + b - 1) / b;
}int main(){size_t block_size = 128;size_t N = 1 * 1024;size_t bytes_A = sizeof(float) * N;size_t bytes_B = sizeof(float) * N;float* h_A = (float*)malloc(bytes_A);float* h_B = (float*)malloc(bytes_B);for( int i = 0; i < N; i++ ){h_A[i] = (i / 666) * ((i % 2 == 0) ? 1: -1);}float* d_A;float* d_B;checkCudaErrors(cudaMalloc(&d_A, bytes_A));checkCudaErrors(cudaMalloc(&d_B, bytes_B));checkCudaErrors(cudaMemcpy( d_A, h_A, bytes_A, cudaMemcpyHostToDevice));cudaEvent_t start, stop;checkCudaErrors(cudaEventCreate(&start));checkCudaErrors(cudaEventCreate(&stop));float msec = 0;int iteration = 1000;checkCudaErrors(cudaEventRecord(start));for(int i = 0; i < iteration; i++){//relu<<<CeilDiv(N, block_size), block_size>>>(d_A, d_B, N);//relu_float4<<<CeilDiv(N, block_size), block_size/4>>>(d_A, d_B, N);relu_float4<<<CeilDiv(N/4, block_size), block_size>>>(d_A, d_B, N);}checkCudaErrors(cudaEventRecord(stop));checkCudaErrors(cudaEventSynchronize(stop));checkCudaErrors(cudaEventElapsedTime(&msec, start, stop));printf("relu takes %.3f msec\n", msec/iteration);checkCudaErrors(cudaMemcpy(h_B, d_B, bytes_B, cudaMemcpyDeviceToHost));for(int i = 0; i < N; i++){double err = fabs(h_B[i] - fmaxf(0.0f, h_A[i]));if(err > 1.e-6) {printf("wrong answer!\n");break;}}cudaFree(d_A);cudaFree(d_B);free(h_A);free(h_B);return 0;
}

编译和运行代码:

nvcc -o relu relu.cu
./relu

4.3、histogram.cu

#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <vector>
#include<assert.h>
#include <algorithm>
#include <cublas_v2.h>
#include <cuda_runtime.h>#define INT4(value) *(int4*)(&(value))
#define FLOAT4(value)  *(float4*)(&(value))#define checkCudaErrors(func)               \
{                                   \cudaError_t e = (func);         \if(e != cudaSuccess)                                        \printf ("%s %d CUDA: %s\n", __FILE__,  __LINE__, cudaGetErrorString(e));        \
}/*
x[i] = i-- -- - -- - - -
- - - - -
考虑一个warp里相邻线程对全局内存y的访问是否合并(coalesced global access)
warp thread[0]: 0, 1, 2, 3, 
warp thread[1]: 4, 5, 6, 7
*/
__global__ void histogram(int* x, int* y, int N){int idx = blockIdx.x * blockDim.x + threadIdx.x;if(idx < N) atomicAdd(&y[x[idx]], 1);
}__global__ void histogram_int4(int* x, int* y, int N) {int idx = 4 * (blockIdx.x * blockDim.x + threadIdx.x);if (idx < N) {int4 tmp_y = INT4(x[idx]);atomicAdd(&(y[tmp_y.x]), 1);atomicAdd(&(y[tmp_y.y]), 1);atomicAdd(&(y[tmp_y.z]), 1);atomicAdd(&(y[tmp_y.w]), 1);}
}template <typename T> 
inline T CeilDiv(const T& a, const T& b) {return (a + b - 1) / b;
}int main(){size_t block_size = 128;size_t N = 32 * 1024 * 1024;size_t bytes_A = sizeof(int) * N;size_t bytes_B = sizeof(int) * N;int* h_A = (int*)malloc(bytes_A);int* h_B = (int*)malloc(bytes_B);for( int i = 0; i < N; i++ ){h_A[i] = i;}int* d_A;int* d_B;checkCudaErrors(cudaMalloc(&d_A, bytes_A));checkCudaErrors(cudaMalloc(&d_B, bytes_B));checkCudaErrors(cudaMemcpy( d_A, h_A, bytes_A, cudaMemcpyHostToDevice));cudaEvent_t start, stop;checkCudaErrors(cudaEventCreate(&start));checkCudaErrors(cudaEventCreate(&stop));float msec = 0;int iteration = 1;checkCudaErrors(cudaEventRecord(start));for(int i = 0; i < iteration; i++){//histogram<<<CeilDiv(N, block_size), block_size>>>(d_A, d_B, N);//histogram_int4<<<CeilDiv(N, block_size), block_size/4>>>(d_A, d_B, N);histogram_int4<<<CeilDiv(N/4, block_size), block_size>>>(d_A, d_B, N);}checkCudaErrors(cudaEventRecord(stop));checkCudaErrors(cudaEventSynchronize(stop));checkCudaErrors(cudaEventElapsedTime(&msec, start, stop));printf("histogram takes %.3f msec\n", msec/iteration);checkCudaErrors(cudaMemcpy(h_B, d_B, bytes_B, cudaMemcpyDeviceToHost));for(int i = 0; i < N; i++){//all ones;double err = fabs(h_B[i] - iteration * 1.0f);if(err > 1.e-6) {printf("wrong answer!\n");break;}}cudaFree(d_A);cudaFree(d_B);free(h_A);free(h_B);return 0;
}

编译和运行代码:

nvcc -o histogram histogram.cu
./histogram

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2812035.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

js里面有引用传递吗?

一&#xff1a;什么是引用传递 引用传递是相对于值传递的。那什么是值传递呢&#xff1f;值传递就是在传递过程中再复制一份&#xff0c;然后再赋值给变量&#xff0c;例如&#xff1a; let a 2; let b a;在这个代码中&#xff0c;let b a; 就是一个值传递&#xff0c;首先…

从零开始学Spring Boot系列-Hello World

欢迎来到从零开始学Spring Boot的旅程&#xff01;我们将从一个非常基础但重要的示例开始&#xff1a;创建一个简单的Spring Boot应用程序&#xff0c;并输出“Hello World”。 1. 环境准备 首先&#xff0c;确保你的开发环境已经安装了以下工具&#xff1a; Java Development …

读人工不智能:计算机如何误解世界笔记04_数据新闻学

1. 计算化和数据化的变革 1.1. 每一个领域都在进行计算化和数据化的变革 1.1.1. 出现了计算社会科学、计算生物学、计算化学或其他数字人文学科 1.1.2. 生活已走向计算化&#xff0c;人们却一点也没有变 1.2. 在如今的计算化和数据化世界中&#xff0c;调查性新闻的实践必须…

掌握ChatGPT润色绝技:什么是人工智能写作以及如何使用它来完成写作任务

如对AI写论文感兴趣&#xff0c;欢迎添加作者wx讨论 : ryan_2982 人工智能 (AI) 的出现开创了技术进步的新时代&#xff0c;彻底改变了包括写作和内容创作在内的各个行业。人工智能写作和人工智能提示已成为可以简化和增强写作任务的强大工具。在这篇博文中&#xff0c;我们将…

2018-02-14 新闻内容爬虫【上学时做论文自己爬新闻数据,原谅我自己懒发的图片】

2018-02-14新闻内容爬虫【上学时做论文自己爬新闻数据&#xff0c;原谅我自己懒发的图片】资源-CSDN文库https://download.csdn.net/download/liuzhuchen/88878591爬虫过的站点&#xff1a; 1QQ新闻 1&#xff0c;准备爬取滚动新闻页面 2 通过F12 开发工具查找发现&#xff…

k8s节点负载使用情况分析命令kubectl describe node [node-name]

1.到任意安装了kubectl节点命令的节点上执行kubectl describe node [node-name] 上面的Requests最小分配 Limits最大分配是所有pod之和&#xff0c;最小分配之和不能超过服务器实际参数&#xff0c;否则新的pod会因为资源不够起不来&#xff0c;最大分配是预设之和&#xff0…

office word保存pdf高质量设置

1 采用第三方pdf功能生成 分辨率越大质量越好

leetcode(算法) 83.删除排序链表中的重复元素(python版)

需求 给定一个已排序的链表的头 head &#xff0c; 删除所有重复的元素&#xff0c;使每个元素只出现一次 。返回 已排序的链表 。 示例 1&#xff1a; 输入&#xff1a;head [1,1,2] 输出&#xff1a;[1,2] 示例 2&#xff1a; 输入&#xff1a;head [1,1,2,3,3] 输出&…

Android WebView访问网页+自动播放视频+自动全屏+切换横屏

一、引言 近期&#xff0c;我发现电视家、火星直播等在线看电视直播的软件都已倒闭&#xff0c;而我奶奶也再无法通过这些平台看电视了。她已六十多岁&#xff0c;快七十岁啦。这些平台的倒下对我来说其实没有多大的影响&#xff0c;但是对于文化不多的她而言&#xff0c;生活中…

大模型学习笔记四:LangChain开发框架解析

文章目录 一、langChain核心组件介绍二、模块I/O封装1&#xff09;多轮对话 Session 封装2&#xff09;模型的输入&#xff08;1&#xff09;Prompt模板封装&#xff08;2&#xff09;从文件加载Prompt模板 3&#xff09;模型的输出&#xff08;1&#xff09;Pydantic (JSON) P…

c入门第二十四篇: 学生成绩管理系统优化(可执行文件传参)

前言 我&#xff1a;“师弟&#xff0c;review完你的代码之后&#xff0c;你觉得有没有什么地方可以优化&#xff1f;” 师弟一脸懵。 我&#xff1a;“比如&#xff0c;你把客户端和服务端的可执行文件生成之后&#xff0c;我把服务端部署到我的测试机器上&#xff0c;客户端…

通过css修改video标签的原生样式

通过css修改video标签的原生样式 描述实现结果 描述 修改video标签的原生样式 实现 在控制台中打开设置&#xff0c;勾选显示用户代理 shadow DOM&#xff0c;就可以审查video标签的内部样式了 箭头处标出来的就是shodow DOM的内容&#xff0c;这些内容正常不可见的&#x…

下载huggingface数据集到本地并读取.arrow文件遇到的问题

文章目录 1. 524MB中文维基百科语料&#xff08;需要下载的数据集&#xff09;2. 下载 hugging face 网站上的数据集3. 读取 .arrow 文件报错代码4. 纠正后代码 1. 524MB中文维基百科语料&#xff08;需要下载的数据集&#xff09; 2. 下载 hugging face 网站上的数据集 要将H…

07_第七章 前端工程化(es6,Vue3,Element_plus组件库)

文章目录 第七章 前端工程化一、前端工程化开篇1.1 什么是前端工程化1.2 前端工程化实现技术栈 二、ECMA6Script2.1. es6的介绍2.2 es6的变量和模板字符串2.3 es6的解构表达式2.4 es6的箭头函数2.4.1 声明和特点2.4.2 实践和应用场景2.4.3 rest和spread 2.5 es6的对象创建和拷贝…

绝地求生:春节部分活动将结束,3月有新版本上线,通行证不偷懒可换成长型

嗨&#xff0c;我是闲游盒~ 感觉过年就在眼前但是已经结束了&#xff0c;时间过的太快了又回归了工作的生活中&#xff0c;而年前更新的28.1新春版本也进行到了小一半的进度。 ◆ 春节版本部分活动即将结束 在大厅首页右上角的活动中心里&#xff0c;春节积分商店和觉醒之旅活动…

MATLAB环境下一种改进的瞬时频率(IF)估计方法

相对于频率成分单一、周期性强的平稳信号来说&#xff0c;具有非平稳、非周期、非可积特性的非平稳信号更普遍地存在于自然界中。调频信号作为非平稳信号的一种&#xff0c;由于其频率时变、距离分辨率高、截获率低等特性&#xff0c;被广泛应用于雷达、地震勘测等领域。调频信…

sqllabs第46关 order by 注入(通过盲注)

打开第46关 提示我们(请将参数输入为sort&#xff08;带数值&#xff09;) 用sort注入排序 尝试操作 order by注入 什么是order by 在MySQL支持使用ORDER BY语句对查询结果集进行排序处理&#xff0c;使用ORDER BY语句不仅支持对单列数据的排序&#xff0c;还支持对数据表中…

vulnhub----hackme2-DHCP靶机

文章目录 一&#xff0c;信息收集1.网段探测2.端口扫描3.目录扫描 二&#xff0c;信息分析三&#xff0c;sql注入1.判断SQL注入2.查询显示位3.查询注入点4.查询库5.查询表6.查字段7. 查user表中的值8.登陆superadmin用户 四&#xff0c;漏洞利用文件上传命令执行蚁剑连接 五&am…

商家入驻平台怎么让资金自动分配给商家

最近很多上线了多商户电商系统的朋友咨询&#xff0c;我们平台的用户支付后&#xff0c;钱进入了我们的对公账户&#xff0c;怎样让钱在走完流程后&#xff0c;自动进入商家的账户呢&#xff1f;今天商淘云为您分享商户入驻平台自动分配给商家资金的三种方法。 首先是平台应建立…

k8s二进制部署的搭建

1.1 常见k8s安装部署方式 ●Minikube Minikube是一个工具&#xff0c;可以在本地快速运行一个单节点微型K8S&#xff0c;仅用于学习、预览K8S的一些特性使用。 部署地址&#xff1a;Install Tools | Kubernetes ●Kubeadm Kubeadm也是一个工具&#xff0c;提供kubeadm init…