CUDA 编程简介(下)

news2024/11/24 13:41:02

文章目录

  • Memory
    • shared memory
    • global memory
    • Transfer Data
    • 异步预取
  • Threads
    • thread block
    • warp
  • GPU 性能
    • 查看性能
    • 测试性能
  • CUDA 流

Memory

在这里插入图片描述

GPU 在 CUDA Mode 下,有多种存储类型:

  • register

    • 位于 SM 上,共 8192 8192 8192 个。作用范围是 thread,读取速度 1 1 1 - cycle latency

    • R/W dependencies:写后读,至少 22 22 22 - cycles 才能稳定(如果同时有 192 192 192 个线程,也就是 6 6 6 个 warps,那么运算速度为 24 24 24 转,此时可以忽略读写依赖)

  • local memory

    • 位于 global memory 上,作用范围是 thread,读取速度 200 200 200 - cycle latency

    • 模拟 register,如果 register 不够用,编译器自动设置。要注意控制各个线程中的 register 的使用数量。

  • shared memory

    • 位于 shared memory 上,作用范围是 block,读取速度 1 1 1 - cycle latency

    • bank conflicts:库冲突,读取延迟变大

  • global memory

    • 位于 global memory 上,作用范围是 grid,读取速度 200 200 200 - cycle latency

    • coalescing accessing:合并访问,可隐藏读取延迟

  • constant and texture memories

    • 位于 global memory 上,作用范围是 grid,读取速度 200 200 200 - cycle latency

    • 由硬件自动调度到对应的 caches 里,hit & miss(如果 hit,那么就如同 register 一样)

shared memory

在古早的 GPU 上,shared memory 只有 16 16 16 个 banks,因此一个 warp 里的 32 32 32 个线程需要按照 “half-warp” 方式来访存。

  1. 如果没有 bank conflict,那么每个 cycle 可以 16 16 16 个 threads 同时读取数据, 2 2 2 个 cycle 就可以读取完毕。
  2. 如果存在 bank conflict,那么这些冲突的 threads 只能串行读取数据了,读取速度慢得多。

在这里插入图片描述

现在的 GPU 已经有了足够多的 banks,如果没有冲突,则可以在 1 1 1 - cycle 内完成一个 warp 的数据读取。另外,如果 warp 里的线程同时读取同一个数据,使用 broadcast 机制,也可以在 1 1 1 - cycle 内完成,这也是 no bank conflict 的情况。

global memory

由于 global memory 的读取延迟很大, 200 200 200 - cycle latency,因此将数据一个一个读取是低效的。可以使用内存合并技术(Coalescing accessing):调度数据时,一次性调度地址整除 64 64 64 的长度 16 16 16 个 words 的内存块,那么 16 16 16 个 half-warp 就可以各自从这个内存块中获取到自己的 word 了。

在这里插入图片描述

现在的 GPU 的一次性调度的内存块大小也变大了,足够支持一个 warp 内的 32 32 32 个线程。我们可以使用 _align_(8) 或者 _align_(16) 来指定任意数据结构大小对齐。

Transfer Data

编程时,一般仅使用 shared memory 以及 global memory。使用 cudaMemcpy() 来调度数据。数据调度流程为:

  1. 将数据从 host 调度到 device 上
  2. 将数据从 device memory 调度到 shared memory 上
  3. 使用 __syncthreads() 同步一个 block 上的所有线程,保证数据全部 ready
  4. 在 shared memory 上执行程序
  5. 如有必要,再次使用 __syncthreads() 同步一个 block 上的所有线程,保证数据全部 updated
  6. 将计算结果从 shared memory 调度到 device memory 上
  7. 将计算结果从 device 调度到 host 上

在这里插入图片描述

为了提高访存效率,应当将数据仔细分类:

  • R/Only:常用的只读变量,放在 constant memory 里,会被自动调度到 cache 里。
  • R/W shared within block:被一个 block 共享的数据,调度到 shared memory 里,每个 thread 各自调度其中的一部分,然后大家共同访问这些数据。
  • R/W within each thread:只被线程自己使用,放在 register 里。但需要注意使用的数量,不要用超了。
  • R/W inputs/results:程序的输入输出,放在 global memory 里。

异步预取

如果使用 cudaMallocManaged(),那么将会创建一致内存 UM,自动在 host 和 device 之间调度数据。每当 device 需要某个数据,而在 device memory 上页面缺失,那么启动一次 HtoDcudaMemcpy;每当 host 需要某个数据,而在 host memory 上页面缺失,那么启动一次 DtoHcudaMemcpy。如果需要大量数据,这种一次次的数据调度会特别慢。将数据异步预取到 device / host 里,大幅降低页面缺失,提高程序的运行速度。

比如,数组相加 a + b = c a+b=c a+b=c

  • 首先把数组 a , b , c a,b,c a,b,c 异步预取到 device 上,进行初始化赋值
  • 然后在 device 上计算 c [ i ] = a [ i ] + b [ i ] c[i] = a[i]+b[i] c[i]=a[i]+b[i]
  • 最后把数组 c c c 异步预取到 host 上,进行正确性检查
#include <stdio.h>

__global__
void initWith(float num, float *a, int N)
{

  int index = threadIdx.x + blockIdx.x * blockDim.x;
  int stride = blockDim.x * gridDim.x;

  for(int i = index; i < N; i += stride)
  {
    a[i] = num;
  }
}

__global__
void addVectorsInto(float *result, float *a, float *b, int N)
{
  int index = threadIdx.x + blockIdx.x * blockDim.x;
  int stride = blockDim.x * gridDim.x;

  for(int i = index; i < N; i += stride)
  {
    result[i] = a[i] + b[i];
  }
}

void checkElementsAre(float target, float *vector, int N)
{
  for(int i = 0; i < N; i++)
  {
    if(vector[i] != target)
    {
      printf("FAIL: vector[%d] - %0.0f does not equal %0.0f\n", i, vector[i], target);
      exit(1);
    }
  }
  printf("Success! All values calculated correctly.\n");
}

int main()
{
  int deviceId;
  int numberOfSMs;

  cudaGetDevice(&deviceId);
  cudaDeviceGetAttribute(&numberOfSMs, cudaDevAttrMultiProcessorCount, deviceId);

  const int N = 2<<24;
  size_t size = N * sizeof(float);

  float *a;
  float *b;
  float *c;

  cudaMallocManaged(&a, size);
  cudaMallocManaged(&b, size);
  cudaMallocManaged(&c, size);

  //异步预取到 GPU(device) 上
  cudaMemPrefetchAsync(a, size, deviceId);
  cudaMemPrefetchAsync(b, size, deviceId);
  cudaMemPrefetchAsync(c, size, deviceId);

  size_t threadsPerBlock;
  size_t numberOfBlocks;

  threadsPerBlock = 256;
  numberOfBlocks = 32 * numberOfSMs;

  cudaError_t addVectorsErr;
  cudaError_t asyncErr;

  initWith<<<numberOfBlocks, threadsPerBlock>>>(3, a, N);
  initWith<<<numberOfBlocks, threadsPerBlock>>>(4, b, N);
  initWith<<<numberOfBlocks, threadsPerBlock>>>(0, c, N);

  addVectorsInto<<<numberOfBlocks, threadsPerBlock>>>(c, a, b, N);

  addVectorsErr = cudaGetLastError();
  if(addVectorsErr != cudaSuccess) printf("Error: %s\n", cudaGetErrorString(addVectorsErr));

  asyncErr = cudaDeviceSynchronize();
  if(asyncErr != cudaSuccess) printf("Error: %s\n", cudaGetErrorString(asyncErr));

  //异步预取到 CPU(host) 上
  cudaMemPrefetchAsync(c, size, cudaCpuDeviceId); 

  checkElementsAre(7, c, N);

  cudaFree(a);
  cudaFree(b);
  cudaFree(c);
}

在使用异步预取进行了一系列重构之后,您应该看到内存传输次数减少了,但是每次传输的量增加了,并且内核执行时间大大减少了。

Threads

thread block

CUDA 里的 block,有如下性质:

  1. 一个 grid 里的所有 threads 执行同一个 kernel 程序(SPMD),使用 block ID 以及 thread ID 来挑选任务。
  2. 同一个 block 里的 threads,可以 share data,可以 synchronize。
  3. 不同 block 里的 threads 无法协作,因为 block 由硬件随机调度,执行顺序是任意的。

同一时间,多个 block 被调度到同一个 SM 上,按照 warp 打散来执行。

warp

一个 warp 内的 threads 实际上是以 SIMD 的方式执行的:

  1. 一个 warp 内的 32 32 32 个 threads 共享指令。
  2. 关于某条 instruction,一旦 warp 内的 32 32 32 个 threads 的数据全部 ready 了(打分板 scoreboard),那么 4 4 4 cycles 将 threads 的这条指令执行完毕。
  3. 这个 4 4 4 cycles 是由工程师人为设定的,因为一条指令的执行需要取址、译码、执行、写回等操作,执行速度过快没什么意义。

在这里插入图片描述

现在的 GPU 可以在 2 2 2 cycles 内执行完一个 warp 的一条指令。

GPU 性能

查看性能

使用 !nvidia-smi 命令可以查看本机 GPU 的性能:

Tue Dec 13 10:24:33 2022       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 440.118.02   Driver Version: 440.118.02   CUDA Version: 10.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|===============================+======================+======================|
|   0  Tesla T4            On   | 00000000:00:1E.0 Off |                    0 |
| N/A   36C    P8     9W /  70W |      0MiB / 15109MiB |      0%      Default |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                       GPU Memory |
|  GPU       PID   Type   Process name                             Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

由于 GPU 上的 SM 数量会因所用的特定 GPU 而异,因此为支持可移植性,您不得将 SM 数量硬编码到代码库中。相反,应该以编程方式获取此信息。为获取操作支持并查看相关介绍,请参阅 CUDA 运行时文档 以帮助识别设备属性结构中的相关属性。

#include <stdio.h>

int main()
{
	int deviceId;
	cudaGetDevice(&deviceId);	// `deviceId` now points to the id of the currently active GPU.

    cudaDeviceProp props;
    cudaGetDeviceProperties(&props, deviceId); // `props` now has many useful properties about the active GPU device.
    
    int computeCapabilityMajor = props.major;
    int computeCapabilityMinor = props.minor;
    int multiProcessorCount = props.multiProcessorCount;
    int warpSize = props.warpSize;
    int maxThreadsPerBlock = props.maxThreadsPerBlock;
    int maxThreadsPerMultiProcessor = props.maxThreadsPerMultiProcessor;

	printf("Device ID: %d\nNumber of SMs: %d\nCompute Capability Major: %d\nCompute Capability Minor: %d\nWarp Size: %d\nMax Threads Per Block: %d\nMax Threads Per MultiProcessor: %d", 
           deviceId, multiProcessorCount, computeCapabilityMajor, computeCapabilityMinor, warpSize, maxThreadsPerBlock, maxThreadsPerMultiProcessor);
    
    return 0;
}

结果为

Device ID: 0
Number of SMs: 40
Compute Capability Major: 7
Compute Capability Minor: 5
Warp Size: 32
Max Threads Per Block: 1024
Max Threads Per MultiProcessor: 1024

测试性能

如要确保优化加速代码库的尝试真正取得成功,唯一方法便是分析应用程序以获取有关其性能的定量信息。nsys 是指 NVIDIA 的Nsight System命令行分析器。该分析器附带于CUDA工具包中,提供分析被加速的应用程序性能的强大功能。

nsys 使用起来十分简单,最基本用法是向其传递使用 nvcc 编译的可执行文件的路径。随后 nsys 会继续执行应用程序,并在此之后打印应用程序 GPU 活动的摘要输出、CUDA API 调用以及统一内存(UM)活动的相关信息。

例如,一个向量加法的 CUDA 程序,先编译它:

!nvcc -std=c++11 -o vector-add-no-prefetch 01-vector-add/01-vector-add.cu -run

接着使用 nsys profile --stats = true 创建一个报告文件,可以在Nsight Systems可视化分析器中打开该文件:

!nsys profile --stats=true -o vector-add-no-prefetch-report ./vector-add-no-prefetch
**** collection configuration ****
	output_filename = /dli/task/vector-add-no-prefetch-report
	force-overwrite = false
	stop-on-exit = true
	export_sqlite = true
	stats = true
	capture-range = none
	stop-on-range-end = false
	Beta: ftrace events:
	ftrace-keep-user-config = false
	trace-GPU-context-switch = false
	delay = 0 seconds
	duration = 0 seconds
	kill = signal number 15
	inherit-environment = true
	show-output = true
	trace-fork-before-exec = false
	sample_cpu = true
	backtrace_method = LBR
	wait = all
	trace_cublas = false
	trace_cuda = true
	trace_cudnn = false
	trace_nvtx = true
	trace_mpi = false
	trace_openacc = false
	trace_vulkan = false
	trace_opengl = true
	trace_osrt = true
	osrt-threshold = 0 nanoseconds
	cudabacktrace = false
	cudabacktrace-threshold = 0 nanoseconds
	profile_processes = tree
	application command = ./vector-add-no-prefetch
	application arguments = 
	application working directory = /dli/task
	NVTX profiler range trigger = 
	NVTX profiler domain trigger = 
	environment variables:
	Collecting data...
Success! All values calculated correctly.
	Generating the /dli/task/vector-add-no-prefetch-report.qdstrm file.
	Capturing raw events...
	9885 total events collected.
	Saving diagnostics...
	Saving qdstrm file to disk...
	Finished saving file.


Importing the qdstrm file using /opt/nvidia/nsight-systems/2019.5.2/host-linux-x64/QdstrmImporter.

Importing...

Importing [==================================================100%]
Saving report to file "/dli/task/vector-add-no-prefetch-report.qdrep"
Report file saved.
Please discard the qdstrm file and use the qdrep file instead.

Removed /dli/task/vector-add-no-prefetch-report.qdstrm as it was successfully imported.
Please use the qdrep file instead.

Exporting the qdrep file to SQLite database using /opt/nvidia/nsight-systems/2019.5.2/host-linux-x64/nsys-exporter.

Exporting 9845 events:

0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************

Exported successfully to
/dli/task/vector-add-no-prefetch-report.sqlite

Generating CUDA API Statistics...
CUDA API Statistics (nanoseconds)

Time(%)      Total Time       Calls         Average         Minimum         Maximum  Name                                                                            
-------  --------------  ----------  --------------  --------------  --------------  --------------------------------------------------------------------------------
   57.6       219929639           3      73309879.7           29951       219841843  cudaMallocManaged                                                               
   37.0       141133435           1     141133435.0       141133435       141133435  cudaDeviceSynchronize                                                           
    5.4        20680929           3       6893643.0         6152223         8231765  cudaFree                                                                        
    0.0           53469           1         53469.0           53469           53469  cudaLaunchKernel                                                                


Generating CUDA Kernel Statistics...

Generating CUDA Memory Operation Statistics...
CUDA Kernel Statistics (nanoseconds)

Time(%)      Total Time   Instances         Average         Minimum         Maximum  Name                                                                            
-------  --------------  ----------  --------------  --------------  --------------  --------------------------------------------------------------------------------
  100.0       141118979           1     141118979.0       141118979       141118979  addVectorsInto                                                                  


CUDA Memory Operation Statistics (nanoseconds)

Time(%)      Total Time  Operations         Average         Minimum         Maximum  Name                                                                            
-------  --------------  ----------  --------------  --------------  --------------  --------------------------------------------------------------------------------
   78.8        78380960        7923          9892.8            1824          128320  [CUDA Unified Memory memcpy HtoD]                                               
   21.2        21123232         768         27504.2            1600          159968  [CUDA Unified Memory memcpy DtoH]                                               


CUDA Memory Operation Statistics (KiB)

            Total      Operations            Average            Minimum            Maximum  Name                                                                            
-----------------  --------------  -----------------  -----------------  -----------------  --------------------------------------------------------------------------------
         393216.0            7923               49.6              4.000              764.0  [CUDA Unified Memory memcpy HtoD]                                               
         131072.0             768              170.7              4.000             1020.0  [CUDA Unified Memory memcpy DtoH]                                               


Generating Operating System Runtime API Statistics...
Operating System Runtime API Statistics (nanoseconds)

Time(%)      Total Time       Calls         Average         Minimum         Maximum  Name                                                                            
-------  --------------  ----------  --------------  --------------  --------------  --------------------------------------------------------------------------------
   55.3      1669733453          87      19192338.5           18686       100126111  poll                                                                            
   40.9      1235491628          83      14885441.3           11203       100244995  sem_timedwait                                                                   
    2.9        88329907         660        133833.2            1006        17394521  ioctl                                                                           
    0.8        22674769          90        251941.9            1396         8168908  mmap                                                                            
    0.0          638962          77          8298.2            2436           21519  open64                                                                          
    0.0          137399          11         12490.8            4708           24628  write                                                                           
    0.0          117980           4         29495.0           23124           37223  pthread_create                                                                  
    0.0          104548          23          4545.6            1412           15906  fopen                                                                           
    0.0           98832           3         32944.0           24763           46457  fgets                                                                           
    0.0           45682          14          3263.0            1697            4494  munmap                                                                          
    0.0           33118           5          6623.6            3206            9203  open                                                                            
    0.0           28823          16          1801.4            1092            3102  fclose                                                                          
    0.0           25011          13          1923.9            1152            3125  read                                                                            
    0.0           13682           2          6841.0            5868            7814  socket                                                                          
    0.0           10983           3          3661.0            3612            3732  pipe2                                                                           
    0.0            8008           5          1601.6            1015            3533  fcntl                                                                           
    0.0            7634           4          1908.5            1767            2072  mprotect                                                                        
    0.0            6467           2          3233.5            2726            3741  fread                                                                           
    0.0            5210           1          5210.0            5210            5210  connect                                                                         
    0.0            3447           1          3447.0            3447            3447  bind                                                                            
    0.0            1841           1          1841.0            1841            1841  listen                                                                          


Generating NVTX Push-Pop Range Statistics...
NVTX Push-Pop Range Statistics (nanoseconds)

然后,在 cmd 里执行 nsight-sys 命令,启动 Nsight Systems

  • 直观地描述由GPU加速的CUDA应用程序的时间表,
  • 识别和利用CUDA应用程序中的优化机会。

在这里插入图片描述

CUDA 流

控制 CUDA 流行为的规则:

  • 给定流中的所有 kernel 会按序执行。
  • 就不同非默认流中的 kernel 而言,无法保证其会按彼此之间的任何特定顺序执行。
  • 默认流具有阻断能力,即,它会等待其它已在运行的所有流完成当前 kernel 之后才运行,但在其自身运行完毕之前亦会阻碍其它流上的 kernel 运行。

在这里插入图片描述

创建、使用、销毁 stream:

cudaStream_t stream;   // CUDA流的类型为 `cudaStream_t`
cudaStreamCreate(&stream); // 注意,必须将一个指针传递给 `cudaCreateStream`

someKernel<<<number_of_blocks, threads_per_block, 0, stream>>>();   // `stream` 作为第4个EC参数传递

cudaStreamDestroy(stream); // 注意,将值(而不是指针)传递给 `cudaDestroyStream`

不过,在 CUDA 的云平台上,不同的非默认 stream 上,它们还是串行执行的。一个流执行完,另一个流才开始执行。

在这里插入图片描述

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

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

相关文章

01. Web漏洞靶场的搭建

01. Web漏洞靶场的搭建 Web漏洞靶场的搭建&#xff08;上&#xff09; 什么是Web安全&#xff1f; 什么是Web Web是互联网的总称&#xff0c;全称为World Wide Web&#xff0c;缩写WWW&#xff0c;即全球广域网&#xff0c;也称为万维网&#xff0c;它是一种基于超文本和HT…

前端入门教程:CSS标准盒模型和怪异盒模型区别

理解盒模型&#xff1a;CSS3 中的盒模型有以下两种&#xff1a;标准盒模型、IE盒子模型(怪异盒模型)&#xff0c;盒模型是由4个部分组成&#xff0c;由内向外分别是content(下图蓝色部分)、padding、border、margin盒模型有5个属性&#xff1a; width 元素宽height 元素高borde…

计算机网络题库---第六章应用层

主要选取谢希仁第八版&#xff0c;复习资料&#xff0c;学校期末划重点 &#xff08;一&#xff09;课本答案 1.互联网的域名结构是怎样的?它与目前的电话网的号码结构有何异同之处&#xff1f; 答&#xff1a; 2.域名系统的主要功能及域名系统中的本地域名服务器、根域名服…

世界杯竞猜项目Dapp-第三章(ERC20)

ERC20 是标准的以太坊 Token 协议&#xff0c;它也是一个合约代码&#xff0c;只要在该合约内部实现了特定的 6 个方法&#xff0c;就会被系统判定为代币合约&#xff0c;具体总结为&#xff1a;6 个必要接口&#xff0c;2 个必要事件&#xff0c;3 个可选接口&#xff0c;详情…

信贷产品年终总结之客群特征画像

临近年末&#xff0c;围绕信贷产品业务的年终总结&#xff0c;是各家金融机构或科技公司的必要工作内容之一。根据实际业务的数据表现进行汇总分析&#xff0c;不仅为回顾过去业务经营的全貌特点&#xff0c;提供了客观的数据分布描述&#xff0c;而且对后期业务开展的策略制定…

H-03卷积神经网络中卷积的作用与原理

目录 1.前言 2.卷积的作用 3.卷积的参数 3.1 卷积核大小&#xff08;kernel_size&#xff09; 3.2 填充&#xff08;padding&#xff09; 3.2.1 same 3.2.2 valid 3.2.3 full 3.3 卷积核算子&#xff08;operator&#xff09; 3.3.1 Robert 算子 3.3.2 Prewitt算子 …

2023就要你换个方式过新年!富而喜悦一年一渡开启新方式!

过去的一年&#xff0c;你过得怎么样&#xff1f;是否有过艰难的逆流时刻&#xff0c;是否拥有过快乐和满足&#xff0c;又是否得到了成长和收获&#xff1f;富而喜悦2023一年一渡财富流新年主题活动就要给你一个礼物多多&#xff01;美美的“礼物”活动&#xff01; 为此&…

艾美捷ichorbio CD4体内抗体,无惧竞争对手

CD4&#xff08;分化簇4&#xff09;是一种在辅助T细胞、调节性T细胞、单核细胞、巨噬细胞和树突状细胞表面表达的糖蛋白。CD4与主要组织相容性复合体&#xff08;MHC&#xff09;的II类分子相互作用&#xff0c;增强T细胞活化的信号。 艾美捷ichorbio CD4体内抗体-低内毒素&am…

基于web得数字媒体资源库系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&…

VCS2 VCS仿真的基础

1、基础知识 编译流程&#xff1a; -Mupdate &#xff1a;增量编译&#xff0c;作用是将需要修改的某个文件修改后重新编译&#xff0c;其.o文件再与其他文件相链接。 -R &#xff1a;编译后立马执行。 -gui &#xff1a;打开DVE的实时GUI。 -l &#xff1a;把编译过程中产生…

CDH6.3.2防止被攻击,打补丁(未授权漏洞)

参考&#xff1a;CDH6.3.2Hadoop默认配置下存在未授权漏洞&#xff0c;禁止匿名访问 - 民宿 - 博客园 这段时间公司的运维大佬扫描安全漏洞的时候&#xff0c;发现有漏洞会被攻击&#xff0c;原因是没有新增用户校验&#xff0c;允许匿名去访问。这样的话。可以操作HDFS和Yarn上…

【iOS】熟悉Objective-C

熟悉Objective-C Objective—C通过一套全新的语法&#xff0c;在C语言基础上添加了面向对象的特性 频繁使用方括号和极长的方法名&#xff0c;使得代码十分易读。 了解Objective-C的起源 Obejective-C与C&#xff0c;java等面向对象的语言类似&#xff0c;在语法上使用“消息结…

【GRU时序预测】基于门控循环单元GRU实现时间序列预测附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

【云原生进阶之容器】第一章Docker核心技术1.3节——命名空间Namespace

1. Linux Namespaces机制简介 Linux Namespace是Linux提供的一种内核级别环境隔离的方法。很早以前的Unix有一个叫chroot的系统调用(通过修改根目录把用户jail到一个特定目录下),chroot提供了一种简单的隔离模式:chroot内部的文件系统无法访问外部的内容。Linux Namespace在…

文件包含漏洞相关协议详解

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是文件包含漏洞相关协议详解。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对未…

执行 pkg -t win index.js 报错 node.js使用pkg打包成exe可执行文件

文章目录一、问题&#xff1a;当执行命令 pkg -t win index.js 的时候报以下错误&#xff1a;二、解决办法&#xff1a;三、安装pkg流程四、其他的打包方法五、题外话&#xff1a;更换exe的icon图标一、问题&#xff1a;当执行命令 pkg -t win index.js 的时候报以下错误&#…

[附源码]计算机毕业设计点餐系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

传奇微端架设好后不亮灯是怎么回事微端程序无连接不更新有连接不更新问题解决办法

传奇微端架设好后不亮灯是怎么回事微端程序无连接不更新有连接不更新问题解决办法 这是在架设传奇微端时很多小伙伴都会遇到的问题&#xff0c;今天艾西来教大家怎么解决这个问题 以下图中有打码的望读者理解&#xff08;平台gz&#xff09; 网关配置好后&#xff0c;图中几个电…

pikachu靶场-11 SSRF漏洞

SSRF漏洞 概述 SSRF(Server-Side Request Forgery:服务器端请求伪造) 其形成的原因大都是由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制 导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据 数据…

Allegro如何把分离的线段变成封闭连续的图形

Allegro如何把分离的线段变成封闭连续的图形 Allegeo支持把分离的线段变成封闭连续的图形,以下图为例,线段是分离的 具体操作如下 选择shape-compose shape Option选择一个层面,比如画在Board Geometry outline层 Find选择other segs 和Lines 框选图形 鼠标右击选择d…