标签归档: Python

NVIDIA 为 CUDA 添加原生 Python 支持:开启 GPU 计算新篇章

引言

在最近的 GTC 大会上,NVIDIA 宣布为其 CUDA 工具包引入原生 Python 支持,这一举措可能彻底改变 Python 开发者使用 GPU 计算的方式。作为全球最流行的编程语言之一,Python 在数据科学、机器学习和科学计算领域的广泛应用促使了这一更新。NVIDIA 此举不仅降低了 GPU 编程的门槛,还可能进一步推动其在全球开发者社区中的普及,尤其是在印度和巴西等发展中国家。

背景

CUDA 是 NVIDIA 推出的并行计算平台,旨在加速各种计算任务。自 2020 年以来,CUDA 的用户数量从 200 万激增至 2023 年的 400 万,显示出其在开发者中的日益重要性。与此同时,根据 GitHub Blog: Octoverse 2024 Analysis 的数据,Python 在 2024 年超越 JavaScript,成为最受欢迎的编程语言。这一趋势为 NVIDIA 提供了契机,通过整合 Python 支持来吸引更多开发者,尤其是那些习惯使用 Python 进行数据分析和 AI 开发的群体。

CUDA Python 的新功能

NVIDIA 为 CUDA Python 引入了一系列新功能,旨在提升开发效率并简化 GPU 编程:

  • 即时编译(JIT Compilation)
    JIT 编译减少了代码的依赖性,使开发者能够更轻松地管理和部署项目。通过在运行时动态编译代码,这一功能还能提升性能,减少对预编译二进制文件的需求。
  • CUDA Core
    被描述为“Python 风格的 CUDA 运行时重新设计”,CUDA Core 为 Python 开发者提供了更直观的接口来管理 GPU 资源。这对于不熟悉传统 GPU 编程的用户来说尤为友好。
  • NVMath Python
    该组件统一了主机(CPU)和设备(GPU)的库调用,简化了跨架构的代码开发。对于需要在 CPU 和 GPU 之间切换的应用程序,这大大提高了开发效率。
  • cuPyNumeric
    cuPyNumeric 是 NumPy 的 GPU 加速替代品。根据 NVIDIA Developer: cuPyNumeric Overview 的介绍,开发者只需更改 import 语句,就能将现有的 NumPy 代码迁移到 GPU 上运行。这一功能基于 Legate 框架,支持从单 CPU 系统扩展到多节点多 GPU 集群,特别适合处理大规模数据集的研究人员和数据科学家。
  • CuTile
    CuTile 是一种专注于数组级处理的新编程模型,旨在简化 GPU 计算的编码和调试工作。目前它主要为 Python 开发,未来计划扩展到 C++,以覆盖更广泛的开发者群体。

技术细节与支持库

CUDA Python 还包括一些增强功能的组件:

  • cuda.core:提供对 CUDA 运行时和核心功能的 Python 风格访问。
  • cuda.bindings:为高级用户提供对 CUDA C API 的低级 Python 绑定。
  • cuda.cooperative:支持高效的并行算法,如排序、扫描、归约和变换。
  • cuda.parallel:为 Numba CUDA 内核提供 CUB 的块级和线程级原语。

此外,nvmath-python 提供了 CPU 和 GPU 的数学库支持,进一步丰富了科学计算的生态系统。

潜在影响

这一更新有望显著降低 Python 开发者使用 GPU 的门槛,尤其是在数据科学、人工智能和科学模拟等领域。cuPyNumeric 使 NumPy 代码无需大幅修改即可扩展到 GPU 集群,这可能彻底改变研究人员处理大规模数据问题的方式。例如,计算流体力学、机器学习模型训练和高能物理等应用都将受益于更快的处理速度。对于发展中国家而言,Python 的易用性结合 CUDA 的强大性能,可能推动高性能计算资源的普及。NVIDIA 的这一战略不仅提升了开发者的生产力,还可能在全球范围内激发更多创新。

结论

NVIDIA 为 CUDA 添加原生 Python 支持是对 Python 在计算领域日益增长需求的积极回应。通过引入 JIT 编译、CUDA Core、NVMath Python、cuPyNumeric 和 CuTile 等功能,NVIDIA 不仅简化了 GPU 编程,还扩大了其潜在用户群。这一发展有望赋能新一代开发者,尤其是发展中国家的技术人才,让他们能够利用 GPU 的强大能力开发尖端应用。随着生态系统的不断完善,例如 CuTile 未来对 C++ 的支持,GPU 计算的普及性和多功能性将进一步提升。

参考资料

| 1 分2 分3 分4 分5 分 (5.00- 1票) Loading ... Loading ... | 归档目录:AI技术 | 同时打有标签:, , |

基于Dlib、Flask和Sqlite的人脸检测和识别服务

这个十一原定的计划取消了,没有做好备份计划,也就不打算出远门了,关在家里,把一直都想做的一个本地化的人脸识别服务整了一下。提供人脸分析的开源服务似乎很多年都没有大的变化了,一直都是Dlib和OpenCV,对比了一下,Dlib更容易使用。一直没有正经写过Python代码,翻出N年前买的Python编程书,边翻书Google、边写代码。基本的代码流程比较简单,Dlib官方也有例子,很容易运行起来,但是要服务化,要做人脸比对,并且是增量的人脸比对和识别,并不容易。说做就做,最终整个服务形成如下架构。

架构图:
image

代码和部署使用方法在如下git工程:https://git.codefine.site:3000/Shentar/facerec

首先需要将探测的过的“人脸”存储起来,然后能输入一张人脸返回与该人脸近似的所有人脸,这样客户端好做人脸归集。很快做好了一个初步的框架:使用Flask提供REST接口接收照片,在响应中返回人脸的特征标识,使用SHA256对人脸68点位的描述向量进行HASH,返回给客户端。同时将HASH值和实际的token存储到Sqlite。第一天大概就完工了这个功能。

运行起来,发现单纯的Flask不能并发,第二个请求会报错,一次只能接受和处理一个请求。于是又按照网上的经验,使用Gunicorn和Gevent来做多线程的方案,因为习惯了单进程多线程的方式,多线程访问Sqlite需要加锁,按照通用的做法,使用一个队列来管理Sqlite实例。继续验证,发现多线程并不能加速Detect的效率,貌似Dlib不支持多线程加速。调整为多进程,四个CPU都能运用起来。

1d2dd2b5bcde40b6a563996821d84843

终于找到了一个能将这个3.2GHZ的四核CPU跑满的业务了 ^_^

Architecture: x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   39 bits physical, 48 bits virtual
CPU(s):                          4
On-line CPU(s) list:             0-3
Thread(s) per core:              2
Core(s) per socket:              2
Socket(s):                       1
NUMA node(s):                    1
Vendor ID:                       GenuineIntel
CPU family:                      6
Model:                           94
Model name:                      Intel(R) Core(TM) i3-6100T CPU @ 3.20GHz

人脸检测的效果还不错,错误率的话,自己家用是够了。特别是在侧脸检测上面,比较准确。在人脸比对方面,错误率就要高一些了,反复验证,发现0.36的比对阀值比较合适。侧脸虽然检测率高,但是在比对上面,只用通用的拟合范数,结果会表现为差异很大。因此这里应该是需要有定制化的比对实现,只做部分比对。这块需要深入到人脸检测技术内部,去分析128D的特征值向量的每一个值,短时间内没办法去研究透了。

由于采用了多进程,因此没法共用一个Sqlite运行时实例,强行并发读写访问会导致数据库错乱,不得不又做了一个服务来封装Sqlite,多个检测进程输出的人脸特征值都发给该服务来顺序存储,同时也返回给客户端。两个服务之间同样采用REST接口交互。

准备大规模上量,将jAlbum目前使用的线上人脸识别服务切换到这个本地服务上面,又发现检测时长非常高,一张4M的图片,大概需要几秒的时间,并且还有些非常小的区块被检测到了。对于检测慢的问题,考虑降低输入的照片的像素,图片减小后,长宽的像素点都相应减少了,但是人脸的特征点并不会损失太多。因此先对图片进行降低像素和尺寸,识别完成后,对识别到的人脸在照片上的位置也要相应做缩放,对比了一下,原始大小检测和缩放后检测,再对结果做相反的缩放,最终结果误差不大,但是这样能极大提速。对于非人脸和质量不高的人脸被检测到的问题,做了一些粗浅的限制,人脸长宽必须大于100的阀值才认为是正常的人脸。Dlib应该有正统的输出人脸的质量的参数,查了很久,没有找到合适的方法,就只能先这样吧。在比对方面,还有一些重要的概念,没有弄明白,如人脸对齐、年龄、性别检测等,不清楚我的代码里面是否已经有调用已经做了这块。

具体的处理代码:

01data = np.frombuffer(data, np.uint8)
02if data is None:
03    raise Exception('image is required.')
04 
05zoom_ratio = 1
06if data.size > 6 * 1024 * 1024:
07    img = cv2.imdecode(data, cv2.IMREAD_REDUCED_COLOR_4)
08    zoom_ratio = 4
09elif data.size > 4 * 1024 * 124:
10    img = cv2.imdecode(data, cv2.IMREAD_REDUCED_COLOR_2)
11    zoom_ratio = 2
12else:
13    img = cv2.imdecode(data, cv2.IMREAD_COLOR)
14 
15faces = []
16dets = detector(img, 1)

总的来说,开源项目,适合做一下Demo,如果要尽善尽美,那么就要深入到源码,有针对性的去优化检测和比对模型。作为个人的实验和家用还是很不错的。至少在快速编程和服务化这方面。

| 1 分2 分3 分4 分5 分 (5.00- 2票) Loading ... Loading ... | 归档目录:WEB网络, 数码硬件, 架构设计, 移动互联, 软件应用 | 同时打有标签:, , , , |

关于Python的闭包和后期绑定

看到Python程序员的10个常见错误这篇文章中讲到了闭包和后期绑定的问题。

有很多不同的人都对闭包过进行了定义:

阅读全文 »

| 1 分2 分3 分4 分5 分 (4.38- 16票) Loading ... Loading ... | 归档目录:实用脚本, 语言基础 | 同时打有标签:, |