02.上帝之心算法用GPU计算提速50倍
本文介绍了上帝之心的算法及其Python实现,使用Python语言的性能分析工具测算性能瓶颈,将算法最耗时的部分重构至CUDA C语言在纯GPU上运行,利用GPU核心更多并行更快的优势显著提高算法运算速度,实现了结果不变的情况下将耗时缩短五十倍的目标。
2.1 简单Python画曼德勃罗特集算法
2.1.1 “上帝之心”的由来
曼德勃罗特集是一个几何图形,曾被称为“上帝的指纹”。

只要计算的点足够多,不管把图案放大多少倍,都能显示出更加复杂的局部,这些局部既与整体不同,又有某种相似的地方。
图案具有无穷无尽的细节和自相似性。如图所示形产生过程,其中后一个图均是前一个图的某一局部放大:

来源:百度百科
2.2.2 简单py算法实现
跟任意GPT要一个简单Python实现的曼德勃罗特集算法,可以得到以下源码:
def simple_mandelbrot(width, height, real_low, real_high, imag_low, imag_high, max_iters, upper_bound):real_vals = np.linspace(real_low, real_high, width)imag_vals = np.linspace(imag_low, imag_high, height) mandelbrot_graph = np.ones((height, width), dtype=np.float32) for x in range(width):for y in range(height):c = np.complex64(real_vals[x] + imag_vals[y] * 1j)z = np.complex64(0) for i in range(max_iters):z = z ** 2 + c if np.abs(z) > upper_bound:mandelbrot_graph[y, x] = 0break return mandelbrot_graph
加上具体的图片大小,实部虚部,迭代次数,发散阈值,进行计算,并记录计算时间,且保存图像,记录保存时间。
if __name__ == '__main__':t1 = time()mandel = simple_mandelbrot(512, 512, -2, 2, -2, 2, 256, 2.5)t2 = time()mandel_time = t2 - t1t1 = time()fig = plt.figure(1)plt.imshow(mandel, extent=(-2, 2, -2, 2))plt.savefig('mandelbrot.png', dpi=fig.dpi)t2 = time()dump_time = t2 - t1print('It took {} seconds to calculate the Mandelbrot graph.'.format(mandel_time))print('It took {} seconds to dump the image.'.format(dump_time))
在笔者的i5-13490F的CPU上,Python3.12.3版本,输出结果是:
~/Desktop/EXAMPLES/02$ ../bin/python mandelbrot.py
It took 3.529670000076294 seconds to calculate the Mandelbrot graph.
It took 0.06651782989501953 seconds to dump the image.
计算过程耗时3.53秒,存成图片耗时0.067秒。图片如图:

2.2 cProfile性能分析算法函数瓶颈
2.2.1 函数粒度分析性能瓶颈
Python 的 cProfile 模块是一个内置的性能分析工具(Profiler),用于统计代码中各个函数的执行时间、调用次数等详细信息,帮助开发者找出程序的性能瓶颈。
主要功能特点包括:
- 统计每个函数的调用次数和时间:记录函数的总执行时间(包括子函数调用)和单独执行时间(不包括子函数)。
- 生成性能报告:以表格形式输出结果,方便分析热点代码。
- 低开销:相比 profile 模块(纯 Python 实现),cProfile 是 C 语言实现的,对程序运行速度影响较小。
使用-m参数调用cProfile模块,按照累计运行时间降序排列-s cumtime,结果重定向至mandelbrot_cProfile.txt文件。
$ ../bin/python -m cProfile -s cumtime mandelbrot.py > mandelbrot_cProfile.txt
最终结果输出前20行可以得知,mandelbrot.py:10(simple_mandelbrot)就调用了1次,耗时4.016秒,为tottime指标最高的单一函数。
$ head -20 mandelbrot_cProfile.txt
It took 4.01598596572876 seconds to calculate the Mandelbrot graph.
It took 0.10479903221130371 seconds to dump the image.1272295 function calls (1250243 primitive calls) in 4.610 secondsOrdered by: cumulative timencalls tottime percall cumtime percall filename:lineno(function)65/2 0.000 0.000 4.503 2.252 text.py:926(get_window_extent)101/2 0.002 0.000 4.503 2.252 text.py:358(_get_layout)1 4.016 4.016 4.016 4.016 mandelbrot.py:10(simple_mandelbrot)32 0.001 0.000 0.632 0.020 __init__.py:1(<module>)349/7 0.001 0.000 0.424 0.061 <frozen importlib._bootstrap>:1349(_find_and_load)346/7 0.001 0.000 0.424 0.061 <frozen importlib._bootstrap>:1304(_find_and_load_unlocked)331/7 0.001 0.000 0.423 0.060 <frozen importlib._bootstrap>:911(_load_unlocked)
PS: tottime(直接运行时间)表示函数本身运行的时间,不包括调用其他函数的时间,它是函数内部执行代码的时间总和,不考虑子函数的执行时间。而 cumtime(累积运行时间)表示函数及其所有子函数运行的总时间,它包括函数本身的时间(tottime)加上所有被该函数调用的子函数的时间总和。
2.2.2 逐行耗时分析性能瓶颈
cProfile模块最小粒度为函数,如果想逐行分析,可以使用line_profiler模块。
line_profiler 是一个第三方库,可以显示每行代码的执行时间、次数和耗时占比。
首先安装该模块:
$ ../bin/pip install line_profiler
Collecting line_profilerDownloading line_profiler-4.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (34 kB)
Downloading line_profiler-4.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (720 kB)━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 720.1/720.1 kB 3.9 MB/s eta 0:00:00
Installing collected packages: line_profiler
Successfully installed line_profiler-4.2.0
然后在需要分析的函数名称前加上@profile装饰器。
@profile
def simple_mandelbrot(width, height, real_low, real_high, imag_low, imag_high, max_iters, upper_bound):real_vals = np.linspace(real_low, real_high, width)imag_vals = np.linspace(imag_low, imag_high, height)...
最后使用kernprof命令行工具运行脚本,-l 表示逐行分析,-v 表示运行后立即显示结果。
~/Desktop/EXAMPLES/02$ ../bin/kernprof -l -v mandelbrot.py
It took 8.354495286941528 seconds to calculate the Mandelbrot graph.
It took 0.07214522361755371 seconds to dump the image.
Wrote profile results to mandelbrot.py.lprof
Timer unit: 1e-06 sTotal time: 6.02906 s
File: mandelbrot.py
Function: simple_mandelbrot at line 9Line # Hits Time Per Hit % Time Line Contents
==============================================================9 @profile 10 def simple_mandelbrot(width, height, real_low, real_high, imag_low, imag_high, max_iters, upper_bound):11 1 57.4 57.4 0.0 real_vals = np.linspace(real_low, real_high, width)12 1 16.5 16.5 0.0 imag_vals = np.linspace(imag_low, imag_high, height)13 14 # we will represent members as 1, non-members as 0.15 1 274.7 274.7 0.0 mandelbrot_graph = np.ones((height, width), dtype=np.float32)16 17 513 53.5 0.1 0.0 for x in range(width):18 262656 28811.2 0.1 0.5 for y in range(height):19 262144 306395.3 1.2 5.1 c = np.complex64(real_vals[x] + imag_vals[y] * 1j)20 262144 75984.6 0.3 1.3 z = np.complex64(0)21 22 7282380 791951.4 0.1 13.1 for i in range(max_iters):23 7257560 1193944.6 0.2 19.8 z = z ** 2 + c24 25 7257560 3568029.4 0.5 59.2 if np.abs(z) > upper_bound:26 237324 40273.0 0.2 0.7 mandelbrot_graph[y, x] = 027 237324 23266.9 0.1 0.4 break28 29 1 1.0 1.0 0.0 return mandelbrot_graph
使用line_profiler模块会拖慢函数,从3秒慢到了8秒。运行结果是函数逐行的耗时,其中: - Hits:该行执行次数 - Time:该行总耗时(微秒) - % Time:该行占函数总耗时的百分比。
耗时最多的三行,功能分别是控制每个像素点的迭代次数(max_iters 次)、曼德勃罗集的迭代公式(复数运算)、和检查曼德勃罗集(Mandelbrot)的逃逸条件(判断复数 z 的模是否超过阈值 upper_bound),耗时多的原因是执行次数过多,各执行了7,257,560 次,每次都要运行复数平方运算(z ** 2)和复数的模(np.abs(z))需要浮点计算。
for i in range(max_iters):z = z ** 2 + cif np.abs(z) > upper_bound:
这三行代码的运算时间之和占整体的92.1%,如果优化这里可以显著降低算法运行时间,提高效率。
2.3 PyCUDA之gpuarray显卡跑算法
2.3.1 “Hello World”
跟任意GPT要个gpuarray的“Hello World”代码,可以得到类似如下代码。注释部分也是GPT添加的。
import numpy as np
#自动内存管理:使用 pycuda.autoinit 自动管理CUDA上下文,简化了代码,适合简单的脚本。
import pycuda.autoinit
#PyCUDA 提供了类似 NumPy 的接口,使得在 GPU 上进行数组操作非常直观和方便。
from pycuda import gpuarray
#创建主机数组:使用 NumPy 创建一个数组 host_data,包含元素 [1, 2, 3, 4, 5],数据类型为 float32。dtype=np.float32 确保数组的数据类型为单精度浮点数,这对于GPU计算很重要,因为 GPU 在处理浮点数时通常更高效。确保主机数组和GPU数组的数据类型一致(如 float32)可以避免潜在的错误和性能问题。
host_data = np.array([1,2,3,4,5] , dtype=np.float32)
#将主机数组传输到 GPU:使用 gpuarray.to_gpu() 方法将主机数组 host_data 传输到 GPU 上,并存储在 device_data 中。device_data 现在是一个GPU数组,存储在 GPU 的显存中。
device_data=gpuarray.to_gpu(host_data)
#在 GPU 上进行逐元素乘法操作:使用 2 * device_data 对 GPU 数组 device_data 中的每个元素乘以 2。这个操作在 GPU 上并行执行,速度比在 CPU 上逐元素操作快得多。结果存储在新的 GPU 数组 device_data_x2 中。
device_data_x2 = 2 * device_data
#将结果从 GPU 传输回主机,使用 .get() 方法将 GPU 数组 device_data_x2 中的数据传输回主机内存,并存储在 host_data_x2 中。host_data_x2 是一个 NumPy 数组,包含操作后的结果。
host_data_x2=device_data_x2.get()
print(host_data_x2)
运行一下,得到如下结果:
$ ../bin/python gpuarray.py
[ 2. 4. 6. 8. 10.]
这是我们第一段在显卡上直接运行代码。
需要注意的是,向显卡发送数据时,需要通过NumPy显示声明数据类型。这样做的好处有两个:
- 避免类型转换带来不必要的开销,消耗更多的计算时间或内存;
- 后续会用CUDA C语言来内联编写代码,必须为变量声明规定具体的类型,否则C代码无法工作,毕竟C是编译型语言
2.3.2 GPU和CPU工作原理的差异
前文的案例中,逐元素乘以常量的操作,是可以并行化运行的,因为一个元素的计算并不依赖其他任何元素的计算结果。
所以在gpuarray的线程上执行该操作时,PyCUDA可以将乘法操作转移至一个个单独的线程上,而不用像CPU一样一个接一个地串行计算。这也是GPU高吞吐的原因,CPU则是高性能。
- 可以将GPU类比于迅雷,每秒下载几兆的数据,倘若有延迟一两秒大家也不关心,大家更关心传输量大,此处“网很快、下载得快”的意思就是吞吐大,每秒多少兆。
- CPU类似于打网络游戏,延迟一般要求低于30ms,倘若延迟大于200ms网络游戏就几乎没有体验可言了,技能释放慢个几百毫秒结果就完全不同,但是丝毫不关心吞吐量,此处“网络很快”的意思就是延迟极低。
日常使用电脑的过程中,主要追求的也是低延迟。鼠标拖动的时候,肉眼不可以看到停顿,键盘按下去屏幕上立刻出现字符,桌面快捷方式双击后,程序窗口要立即出现,在程序之间切换要流畅自如毫无拖沓。
而什么场景需要显卡呢?典型场景,也是显卡迄今为止最为主要的工作内容,就是游戏画面渲染,一草一木、光影追踪,游戏两个最为核心的指标,画质和帧率,也就是渲染的画面的质量(像素点的多少)和每秒可以渲染多少张,此时评价显卡很快的意思就是,每秒出的图又细又多,也就是高吞吐。每秒出10张480p的图,相比每秒出100张1080p的图,玩的游戏体验不在一个次元上。
再来看一段GPU和CPU跑相同算法的速度对比。编写一段代码(time_calc.py),分别在CPU和GPU上运行同样的常量乘法计算,对比执行速度。
import numpy as np
import pycuda.autoinit
from pycuda import gpuarray
from time import time
#创建五千万个随机单精度浮点数
host_data = np.float32(np.random.random(50000000))
#CPU计算耗时
t1 = time()
host_data_2x = host_data * np.float32(2)
t2 = time()
print('total time to compute on CPU: %f' % (t2 - t1))
#传输到显卡进行计算耗时
device_data = gpuarray.to_gpu(host_data)
t1 = time()
device_data_2x = device_data * np.float32(2)
t2 = time()
#数据从显卡传回主机
from_device = device_data_2x.get()
#比较 CPU 和 GPU 的计算结果是否相同
print('total time to compute on GPU: %f' % (t2 - t1))
print('Is the host computation the same as the GPU computation? : {}'.format(np.allclose(from_device, host_data_2x)))
在笔者机器i5-13490F、RTX5060ti 12G上运行三次,对比差异:
$ ../bin/python time_calc.py
total time to compute on CPU: 0.043279
total time to compute on GPU: 0.058837
Is the host computation the same as the GPU computation? : True
$ ../bin/python time_calc.py
total time to compute on CPU: 0.047776
total time to compute on GPU: 0.058785
Is the host computation the same as the GPU computation? : True
$ ../bin/python time_calc.py
total time to compute on CPU: 0.046850
total time to compute on GPU: 0.057116
Is the host computation the same as the GPU computation? : True
可以发现CPU的速度几乎和GPU一样的快,这是什么原因呢?因为NumPy可以利用现代CPU中的SSE指令来加速计算,在某些场景中性能可以与GPU相媲美。
可以把浮点数的个数设置成五亿个:
host_data = np.float32(np.random.random(500000000))
再运行三次对比差异:
$ ../bin/python time_calc.py
total time to compute on CPU: 0.437335
total time to compute on GPU: 0.263772
Is the host computation the same as the GPU computation? : True
$ ../bin/python time_calc.py
total time to compute on CPU: 0.436809
total time to compute on GPU: 0.056556
Is the host computation the same as the GPU computation? : True
$ ../bin/python time_calc.py
total time to compute on CPU: 0.438307
total time to compute on GPU: 0.060931
Is the host computation the same as the GPU computation? : True
可以看到在第二次、第三次运行时,GPU的耗时约为CPU的十分之一,并行提速效果显著。可以推理得到倘若数据量更大会提速更多。
那为什么第一次GPU耗时偏多呢?因为PyCUDA编写的代码中的CUDA逻辑部分第一次运行时需要使用NVCC编译器编译成字节码,以供PyCUDA调用,所以第一次运行时间会长一些;后续再次调用时,如果代码没有修改,则直接使用已经编译好的缓存即可,这与我们玩一些3A大作的游戏,第一次运行需要进行“着色器编译”是相同的原理。
2.4 PyCUDA之内联CUDA C算法提速
对gpuarray对象进行操作,默认会在纯GPU上执行,上一节对元素乘以2时,这个对象2会传输到GPU上,由GPU在显存中创建对象,在显卡的核心上并行计算。
如果操作涉及gpuarray与主机数据(或变量如numpy数组)的混合运算,PyCUDA会报错,因为它无法隐式决定数据位置。比如:
# 会报错!不能直接混合gpuarray和CPU创建的numpy数组
device_data_2x = device_data * np.ones(100)
必须显式将数据放置在纯GPU(或纯CPU)上。那具体代码如何写呢?这里就可以引入ElementwiseKernel函数,直接内联CUDA C代码编程,追求最为设备原生的高性能。下面上案例(simple_element_kernel_example0.py):
import numpy as np
import pycuda.autoinit
from pycuda import gpuarray
from time import time
#用于创建元素级操作的CUDA内核
from pycuda.elementwise import ElementwiseKernel
host_data = np.float32(np.random.random(500000000))
# 定义一个CUDA元素级内核:输入参数:两个float指针(in和out),操作:将输入数组的每个元素乘以2,结果存入输出数组,内核名称:"gpu_2x_ker"
gpu_2x_ker = ElementwiseKernel("float *in, float *out","out[i] = 2*in[i];","gpu_2x_ker"
)
def speedcomparison():t1 = time()host_data_2x = host_data * np.float32(2)t2 = time()print('total time to compute on CPU: %f' % (t2 - t1))device_data = gpuarray.to_gpu(host_data)# 在GPU上分配与输入数组大小相同的空输出数组device_data_2x = gpuarray.empty_like(device_data)t1 = time()# 调用之前定义的CUDA内核在GPU上执行计算gpu_2x_ker(device_data, device_data_2x)t2 = time()from_device = device_data_2x.get()print('total time to compute on GPU: %f' % (t2 - t1))print('Is the host computation the same as the GPU computation? : {}'.format(np.allclose(from_device, host_data_2x)))
if __name__ == '__main__':speedcomparison()
这样包括输入的所有参数、运算符和输出,都是在纯GPU的设备里操作,达到设备级别的原生高性能。同样多运行几次,观察速度差异:
$ ../bin/python simple_element_kernel_example0.py
total time to compute on CPU: 0.431743
total time to compute on GPU: 0.565969
Is the host computation the same as the GPU computation? : True
$ ../bin/python simple_element_kernel_example0.py
total time to compute on CPU: 0.436628
total time to compute on GPU: 0.062304
Is the host computation the same as the GPU computation? : True
$ ../bin/python simple_element_kernel_example0.py
total time to compute on CPU: 0.433212
total time to compute on GPU: 0.055214
Is the host computation the same as the GPU computation? : True
同样可以观察到与前文一样的现象,首次运行CUDA C部分需要先用NVCC编译,再次运行速度才会获得显著提升。
PS:思考:前文的混合运算这样写:device_data_2x = device_data * device_data,可以吗?答案是可以的,这表示两个GPU数组(gpuarray)之间的逐元素乘法,PyCUDA会将乘法运算符转成CUDA C的乘法,这个操作会完全在纯GPU上并行执行。
2.5 纯GPU重构算法比CPU快五十倍
那最后的任务就是把耗时占92.1%的以下三行代码用CUDA C重写,使之充分利用显卡并行计算大吞吐的特性,进行充分的加速。
for i in range(max_iters):z = z ** 2 + cif np.abs(z) > upper_bound:
算法开发和移植是当前工资最高的工作,可惜我不会,我只能问GPT。可悲的是,如果不会算法,连怎么调试,生成的结果对不对,模型有没有出现幻觉,都无法判断,毕竟在算法这个领域,GPT的能力大于自己。
幸亏我们的案例来自书籍,有作者调好的版本,同功能的CUDA C算法实现如下,可以说与Python的写法几乎一模一样:
mandelbrot_graph[i] = 1;
pycuda::complex<float> c = lattice[i];
pycuda::complex<float> z(0,0);
for (int j = 0; j < max_iters; j++)
{z = z*z + c; if(abs(z) > upper_bound){mandelbrot_graph[i] = 0;break;}
}
同样算法的各种参数也需要改变:
def gpu_mandelbrot(width, height, real_low, real_high, imag_low, imag_high, max_iters, upper_bound):# we set up our complex lattice as suchreal_vals = np.matrix(np.linspace(real_low, real_high, width), dtype=np.complex64)imag_vals = np.matrix(np.linspace(imag_high, imag_low, height), dtype=np.complex64) * 1jmandelbrot_lattice = np.array(real_vals + imag_vals.transpose(), dtype=np.complex64) # copy complex lattice to the GPU#gpuarray.to_gpu函数只能处理NumPy的array类型,所以发送到GPU之前要进行包装;mandelbrot_lattice_gpu = gpuarray.to_gpu(mandelbrot_lattice)# allocate an empty array on the GPU#gpuarray.empty函数在GPU上分配内存,指定大小、形状及类型,可以看作是C语言中的malloc函数;比C的优点是不需要惦记内存释放或回收,因为gpuarray对象在析构时会自动清理。mandelbrot_graph_gpu = gpuarray.empty(shape=mandelbrot_lattice.shape, dtype=np.float32)#注意CUDA C里的模板类型pycuda::complex和Python代码里的NumPy的Complex64是对应的,否则参数传递过去是无法解析的。比如CUDA C的int类型对应NumPy的int32类型,CUDA C的float类型对应NumPy的float32类型。另外,数组传递给CUDA C时,会被视为C指针。mandel_ker(mandelbrot_lattice_gpu, mandelbrot_graph_gpu, np.int32(max_iters), np.float32(upper_bound)) mandelbrot_graph = mandelbrot_graph_gpu.get() return mandelbrot_graph
与原来的纯Python相比逻辑是一样的,只是多了各种数据格式的转换和映射,最后就是激动人心的测速环节,还是i5-13490F、RTX5060ti 12G的机器:
~/Desktop/EXAMPLES/02$ ../bin/python gpu_mandelbrot.py
It took 0.1877138614654541 seconds to calculate the Mandelbrot graph.
It took 0.09330153465270996 seconds to dump the image.
~/Desktop/EXAMPLES/02$ ../bin/python gpu_mandelbrot.py
It took 0.05863165855407715 seconds to calculate the Mandelbrot graph.
It took 0.07119488716125488 seconds to dump the image.
~/Desktop/EXAMPLES/02$ ../bin/python gpu_mandelbrot.py
It took 0.062407732009887695 seconds to calculate the Mandelbrot graph.
It took 0.06969809532165527 seconds to dump the image.
同理第一次运行,是NVCC编译花了一些时间,后面稳定在0.06秒左右的水平,从3.53秒到0.06秒,大概是59倍的性能提升。
当然,需要对比确认下生成的PNG图片是一致的。本章节的任务成功完成。通过这个实验相信大家对GPU特性的理解可以说是非常深刻了。
PS:最后又让deepseek帮助优化了一下代码,执行ds优化后的版本,生成同样的图,速度降到了0.0036秒,是书中代码的1/20,可见,优化是深不见底的学问。

- 代码等附件下载地址:https://github.com/r0ysue/5060STUDY
引用来源: - 《GPU编程实战(基于Python和CUDA)》、deepseek
相关文章:
02.上帝之心算法用GPU计算提速50倍
本文介绍了上帝之心的算法及其Python实现,使用Python语言的性能分析工具测算性能瓶颈,将算法最耗时的部分重构至CUDA C语言在纯GPU上运行,利用GPU核心更多并行更快的优势显著提高算法运算速度,实现了结果不变的情况下将耗时缩短五…...
MES管理系统:Java+Vue,含源码与文档,实现生产过程实时监控、调度与优化,提升制造企业效能
前言: 在当今竞争激烈的制造业环境中,企业面临着提高生产效率、降低成本、提升产品质量以及快速响应市场变化等多重挑战。MES管理系统作为连接企业上层计划管理系统与底层工业控制之间的桥梁,扮演着至关重要的角色。它能够实时收集、分析和处…...
LeetCode算法题 (搜索二维矩阵)Day18!!!C/C++
https://leetcode.cn/problems/search-a-2d-matrix/description/ 一、题目分析 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 ta…...
VectorStore 组件深入学习与检索方法
考虑到目前市面上的向量数据库众多,每个数据库的操作方式也无统一标准,但是仍然存在着一些公共特征,LangChain 基于这些通用的特征封装了 VectorStore 基类,在这个基类下,可以将方法划分成 6 种: 相似性搜…...
HackMyVM-First
信息搜集 主机发现 ┌──(kali㉿kali)-[~] └─$ nmap -sn 192.168.43.0/24 Starting Nmap 7.95 ( https://nmap.org ) at 2025-05-31 06:13 EDT Nmap scan report for 192.168.43.1 Host is up (0.0080s latency). MAC Address: C6:45:66:05:91:88 (Unknown) …...
30V/150A MOSFET 150N03在无人机驱动动力系统中的性能边界与热设计挑战
产品技术概述 150N03 是一款基于沟槽式工艺(Trench Technology)的N沟道功率MOSFET,其核心价值在于: 电压/电流规格:VDSS30V, ID150A (Tc25℃) 工艺特征:高密度元胞设计实现超低导通电阻 双面散热架构:顶部裸露铜架底…...
数据共享交换平台之数据资源目录
依据信息资源体系规范,构建多维度、多层级的资源目录体系,完整的展示和管理资源目录。资源目录提供以下功能: 多层级资源目录展示,能够将资源目录按照技术维度和管理维度进行分类管理,并能够将资源目录按照数据湖、基础…...
跨平台浏览器集成库JxBrowser 支持 Chrome 扩展程序,高效赋能 Java 桌面应用
JxBrowser 是 TeamDev 开发的跨平台库,用于在 Java 应用程序中集成 Chromium 浏览器。它支持 HTML5、CSS3、JavaScript 等,具备硬件加速渲染、双向 Java 与 JavaScript 连接、丰富的事件监听等功能,能处理网页保存、打印等操作,助…...
WEBSTORM前端 —— 第3章:移动 Web —— 第3节:移动适配
目录 一、移动Web基础 1.谷歌模拟器 2.屏幕分辨率 3.视口 4.二倍图 二、适配方案 三、rem 适配方案 四、less 1.less – 简介 2.less – 注释 3.less – 运算 4.less – 嵌套 5.less – 变量 6.less – 导入 7.less – 导出 8.less – 禁止导出 五…...
38.springboot使用rabbitmq
pom依赖 <!--amqp依赖,包含RabbitMQ--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-amqp</artifactId></dependency> 配置文件添加 spring:application:name: message…...
弱光环境下如何手持相机拍摄静物:摄影曝光之等效曝光认知
写在前面 博文内容为一次博物馆静物拍摄笔记的简单总结内容涉及:弱光环境拍摄静物如何选择,以及等效曝光的认知理解不足小伙伴帮忙指正 😃,生活加油 我看远山,远山悲悯 持续分享技术干货,感兴趣小伙伴可以关注下 _ 采…...
Selenium Manager中文文档
1. 什么是 Selenium Manager(测试版) Selenium Manager 是 Selenium 官方提供的命令行工具(用 Rust 实现),用于自动管理浏览器及其驱动(chromedriver、geckodriver、msedgedriver 等)。从 Sele…...
WEB安全--SQL注入--MSSQL注入
一、SQLsever知识点了解 1.1、系统变量 版本号:version 用户名:USER、SYSTEM_USER 库名:DB_NAME() SELECT name FROM master..sysdatabases 表名:SELECT name FROM sysobjects WHERE xtypeU 字段名:SELECT name …...
【HTML】基础学习【数据分析全栈攻略:爬虫+处理+可视化+报告】
- 第 102 篇 - Date: 2025 - 05 - 31 Author: 郑龙浩/仟墨 文章目录 HTML 基础学习一 了解HTML二 HTML的结构三 HTML标签1 标题2 文本段落3 换行4 加粗、斜体、下划线5 插入图片6 添加链接7 容器8 列表9 表格10 class类 HTML 基础学习 一 了解HTML 一个网页分为为三部分&…...
SAP Business ByDesign:无锡哲讯科技赋能中大型企业云端数字化转型
云端ERP时代,中大型企业的智能化引擎 在数字经济高速发展的今天,中大型企业面临着全球化竞争、供应链复杂化、数据安全等多重挑战。传统的本地化ERP系统已无法满足企业快速响应市场变化的需求,而SAP Business ByDesign(ByD&…...
华为OD机考2025B卷 - 无向图染色(Java Python JS C++ C )
最新华为OD机试 真题目录:点击查看目录 华为OD面试真题精选:点击立即查看 题目描述 给一个无向图染色,可以填红黑两种颜色,必须保证相邻两个节点不能同时为红色,输出有多少种不同的染色方案? 输入描述 第一行输入M(图中节点数) N(边数) 后续N行格式为:V1 V2表示…...
计算机网络学习20250528
地址解析协议ARP 实现IP地址和Mac地址的转换 ARP工作原理: 每台主机或路由器都有一个ARP表,表项:<IP地址,Mac地址,TTL>(TTL一般为20分钟) 主机产生ARP查询分组,包含源目的IP地…...
Next.js路由导航完全指南
在前端框架(如 React、Vue 等)或移动端开发中,路由系统是实现页面 / 界面导航的核心机制。Next.js 采用 文件系统路由(File System Routing),即根据项目目录结构自动生成路由。 Next.js 目前有两套路由解决…...
五、web安全--XSS漏洞(1)--XSS漏洞利用全过程
本文章仅供学习交流,如作他用所承受的法律责任一概与作者无关1、XSS漏洞利用全过程 1.1 寻找注入点:攻击者首先需要找到目标网站中可能存在XSS漏洞的注入点。这些注入点通常出现在用户输入能够直接输出到页面,且没有经过适当过滤或编码的地方…...
【C++高级主题】命令空间(六):重载与命名空间
目录 一、候选函数与命名空间:重载的 “搜索范围” 1.1 重载集的构成规则 1.2 命名空间对候选函数的隔离 二、重载与using声明:精准引入单个函数 2.1 using声明与重载的结合 2.2 using声明的冲突处理 三、重载与using指示:批量引入命名…...
利用 Python 爬虫获取淘宝商品详情
在电商领域,淘宝作为中国最大的在线零售平台,拥有海量的商品信息。对于开发者、市场分析师以及电商研究者来说,能够从淘宝获取商品详情信息,对于市场分析、价格比较、商品推荐等应用场景具有重要价值。本文将详细介绍如何使用 Pyt…...
动态拼接内容
服务器端模板引擎(Server-Side Template Engine) 的特性,比如 JSP(Java Server Pages)、ASP.NET、PHP 等技术中常用的 <% %> 语法。 它的核心作用是: 动态拼接内容:在 HTML 中嵌入编程语…...
Tomcat运行比较卡顿进行参数调优
在Tomcat conf/catalina.bat或catalina.sh中 的最上面增加参数 1. 初步调整参数(缓解问题) set JAVA_OPTS -Xms6g -Xmx6g -Xmn3g # 增大新生代,减少对象过早晋升到老年代 -XX:MetaspaceSize256m -XX:MaxMetaspaceS…...
java直接获取MyBatis将要执行的动态sql命令(不是拦截器方式)
目录 前言 一. 准备数据 1. 传输过来的json条件数据 2. mybatis 配置的动态sql 3. 想要的最终会执行的sql并返回给页面展示 二. 实现方式 三. 最终代码 前言 1.在平常开发过程中,MyBatis使用时非常多的,一般情况下我们只需要在控制台看看MyBatis输出的日志,要不就是实…...
C++四种类型转换方式
const_cast,去掉(指针或引用)常量属性的一个类型转换,但需要保持转换前后类型一致static_cast,提供编译器认为安全的类型转换(最常使用)reinterpret_cast,类似于c语言风格的强制类型转换,不保证安全;dynamic_cast,主要用于继承结构中…...
Canvas: trying to draw too large(256032000bytes) bitmap.
1、错误展示 测试了一下一张图片的显示,发现二个手机上测试的结果不一样,配制好一些的手机,直接就通过,但是屏小一些的测试手机上,直接报下面的错误。 这个意思是图片太大了,直接就崩了。 2、代码编写 lo…...
【深度学习-pytorch篇】5. 卷积神经网络与LLaMA分类模型
卷积神经网络与LLaMA分类模型 一、卷积操作基础 卷积是深度学习中用于提取局部特征的核心操作,特别适用于图像识别任务。 自定义二维卷积函数示例 以下函数实现了一个简化版的二维卷积: def convolve2D(image, kernel, padding0, strides1):kernel …...
matlab全息技术中的菲涅尔仿真成像
matlab全息技术中的菲涅尔仿真成像程序。 傅里叶法(重建距离得大)/Fresnel.m , 545 傅里叶法(重建距离得大)/FresnelB.m , 548 傅里叶法(重建距离得大)/Fresnel_solution.m , 1643 傅里叶法(重…...
基于对比学习的推荐系统开发方案,使用Python在PyCharm中实现
以下是一个基于对比学习的推荐系统开发方案,使用Python在PyCharm中实现。本文将详细阐述技术原理、系统设计和完整代码实现。 基于对比学习的推荐系统开发方案 一、技术背景与原理 1.1 对比学习核心思想 对比学习(Contrastive Learning)通过最大化正样本相似度、最小化负…...
网络协议之办公室网络是怎样的?
写在前面 本文来看下办公室网络怎样的。 1:正文 如果是在一个寝室中组件一个局域网还是比较简单的,只需要一个交换机,然后大家的电脑全部连接到这个交换机上就行了,之后所有的电脑设置CIDR保证在一个局域网就可以了。但是&#…...
