数据科学

面向 NetworkX 用户的加速生产就绪型图形分析

NetworkX 是一款热门且易于使用的 Python 图形分析库。然而,其性能和可扩展性可能无法满足中型到大型网络的需求,这可能会严重影响用户的工作效率。

NVIDIA 和 ArangoDB 已经通过一项无需更改 NetworkX 代码的解决方案共同解决了这些性能和扩展问题,该解决方案集成了三个主要组件:

  • NetworkX API
  • 使用的图形加速 RAPIDS cuGraph
  • ArangoDB 中的大规模生产就绪型分析

在本文中,我将讨论如何让 NetworkX 用户的生活更轻松,向您展示一个实现示例,并解释如何开始抢先体验。

借助 NetworkX 轻松进行图形分析

NetworkX 广泛用于数据科学家、学生和许多其他人员的图形分析。它是开源的、 WELL-DOCUMENTED 并通过简单的 API 支持大量算法。

也就是说,其一个已知的限制是它在中大型图形方面的性能,这严重地影响了它在生产应用中的实用性。

使用 cuGraph 加速图形分析

RAPIDS cuGraph 图形分析加速库弥合了 NetworkX 与基于 GPU 的图形分析之间的差距:

  • 图形创建和操作:使用 NetworkX 创建和操作图形,将数据无缝传递至 cuGraph,以加速处理大型图形。
  • 快速图形算法:利用 NVIDIA GPUs 的强大功能进行实时分析。
  • 数据互操作性:支持 NetworkX 图形对象和其他格式的数据,实现机器学习、ETL 任务和图形分析之间的简单数据交换。

最棒的地方是,您无需更改代码即可享受 NVIDIA GPU 加速的优势。只需安装 nx-cugraph 库并指定 cuGraph 后端。有关安装和性能基准测试的更多信息,请参阅在 NVIDIA GPU 上加速 NetworkX 以实现高性能图形分析

简而言之,对于大小介于 10 到 1000 之间的 k,GPUs 可将单次 betweenness centrality 运行速度提高 11 到 600 倍。

使用 ArangoDB 进行生产就绪型图形分析

NetworkX 用户通常必须采用一套复杂的方法来持久化图形数据:

  • 手动将数据导出到平面文件
  • 关系型数据库
  • 临时解决方案,例如使用内存存储

每种方法都有一系列独特的挑战,迫使您花费时间和精力来管理和操作图形数据,而不是专注于分析和数据科学任务。

ArangoDB 的数据持久性层可让一个或多个用户更轻松地在任何无法容纳内存的大型网络上执行图形操作。通过将 ArangoDB 集成为持久性数据层,您将看到以下几个潜在优点:

  • 可扩展性:图形数据可以跨多个节点横向扩展,而不仅仅是纵向扩展,从而处理大量数据集。
  • 性能:用于实时分析和操纵图形数据的快速读写操作。
  • 灵活性:在一个完全集成的平台上支持所有热门数据模型:图形、文档、全文本搜索、键/值和地理空间模型;还支持多租户。

图 1 展示了如何将 ArangoDB 集成到 NetworkX 用户的工作流程中,从而改变图形数据的存储和访问方式。通过提供这种新的持久性层,ArangoDB 使数据科学家能够专注于他们擅长的工作,而不是数据操作和其他细节。

Workflow diagram shows starting with a query into NetworkX that has been loaded with data using Python DataFrames and persisting data in ArangoDB.
图 1. ArangoDB 作为 NetworkX 持久性层

数据持久性使用户能够利用其他团队成员完成的工作。数据不必从源加载并编译为每个用户的图形,而是可以从数据库加载图形。

图形算法的结果也可以存储和检索,而不是由每个用户再次运行。最终,这节省了用户的时间和资金。

借助 cuGraph 和 ArangoDB 实现 GPU 加速分析

在 NetworkX 中,分析大型数据集需要很长时间。这就是 ArangoDB 使用 RAPIDS cuGraph 分析图形数据的原因,尤其是在数据增长到足以导致性能降低时。

Workflow diagram shows starting with a query into NetworkX that has been loaded with data using Python DataFrames; using cuGraph in memory on a GPU for algorithms and processing; and persisting data in ArangoDB.
图 2. 使用 ArangoDB、NetworkX 和 cuGraph 分析大规模图形。

通过 NetworkX 接口使用 GPU 扩展 ArangoDB 有几个好处。首先,与使用 CPU 相比,使用 GPU 从 ArangoDB 提取数据的速度要快得多。这是因为 ArangoDB 优化了其数据提取工具,以独特地满足 cuGraph 数据结构的需求,即坐标列表(COO)图形格式。

其次,您可以通过笔记本电脑或其他客户端分析大型图形数据。NetworkX充当客户端API库,用于处理图形算法,这些算法所需的内存超过客户端所能提供的内存。

最后,无需更改代码。cuGraph 支持 NetworkX 用户零代码更改,因此您可以使用自己熟悉的工具。

实施示例

得益于 NetworkX 后端到后端接口的功能,只要机器上有可用的 NVIDIA GPU,nx-arangodb 图形即可使用 nx-cugraph 的 GPU 功能。换言之,当使用 nx-arangodb 时,仍可选择通过 NetworkX 运行 CPU 或 GPU 算法。

以下各节展示了如何使用 NetworkX 和 nx-arangodb 库在 ArangoDB 中创建和持久化图形:

  • 下载数据
  • 创建 NetworkX 图形
  • 在不使用 ArangoDB 的情况下运行 cuGraph 算法
  • 将 NetworkX 图形保留为 ArangoDB
  • 实例化 NetworkX-ArangoDB 图形
  • 使用 ArangoDB 运行 cuGraph 算法

测试环境

在本文中,我使用了具有 13 GB 系统 RAM 的 Intel Xeon CPU,并将其与具有 84 GB 系统 RAM 和 40 GB GPU RAM 的 NVIDIA A100 GPU 进行了比较。我使用的是 CUDA 12.2。

Stanford Network Analysis Platform (SNAP) 引用专利数据集是一张在 1975 年至 1999 年期间授予的专利引文图,总计包含 370 万个节点和 1650 万个边缘。代码示例依赖于 Betweenness Centrality 图形算法,可帮助您找到哪些专利比其他专利更重要,并了解它们的相对重要性。

在本文中,我使用了通过 ArangoGraph 托管服务提供的 ArangoDB 实例,该实例使我能够为未来会话保留任何已创建的图形。它作为企业版 3.11.8,以六个节点(每个节点 32 GB 内存)的分片数据库运行。

下载数据

首先,下载 Citation Patents 数据集,并将其写入文本文件。

# Median Time: 10 seconds  

import gzip
import shutil
import requests

url = 'https://snap.stanford.edu/data/cit-Patents.txt.gz'
name = 'cit-Patents.txt'

# Download gz
response = requests.get(url, stream=True)
response.raise_for_status()

# Stream gz data & write to text file
with response.raw as r, gzip.open(r, 'rb') as f_in, open(name, 'wb') as f_out:
    shutil.copyfileobj(f_in, f_out)

创建 NetworkX 图形

接下来,使用 pandas 边缘列表对 NetworkX 图形进行实例化。

# Median Time: 90 seconds 

import pandas as pd
import networkx as nx

# Read into Pandas 
pandas_edgelist = pd.read_csv(
    "cit-Patents.txt",
    skiprows=4,
    delimiter="\t",
    names=["src", "dst"],
    dtype={"src": "int32", "dst": "int32"},
)

# Create NetworkX Graph from Edgelist
G_nx = nx.from_pandas_edgelist(
    pandas_edgelist, source="src", target="dst", create_using=nx.DiGraph
)

在不使用 ArangoDB 的情况下运行 cuGraph 算法

可以通过将 backend 设置为 cugraph 来调用 NetworkX 算法。这使用 nx-cugraph 的 GPU 加速算法实现,无需更改代码。

# Median Time: 5 seconds

result = nx.betweenness_centrality(G_nx, k=10, backend="cugraph")

或者,设置 NETWORKX_AUTOMATIC_BACKENDS 环境变量,将 cugraph 指定为选定的 NetworkX 后端,而不是指定 backend 参数。

将 NetworkX 图形保留为 ArangoDB

此时,您可以选择将本地 NetworkX 图形保留到 ArangoDB 中。假设您有一个在提供的 DATABASE_HOST 上运行的 ArangoDB 实例,您可以通过实例化一个 NetworkX 对象,并使用参数 along with 一个特定名称来加载图形。

# Median Time: 3 Minutes 

import os
import nx_arangodb as nxadb

os.environ["DATABASE_HOST"] = "https://123.arangodb.cloud:8529"
os.environ["DATABASE_USERNAME"] = "root"
os.environ["DATABASE_PASSWORD"] = "password"
os.environ["DATABASE_NAME"] = "myDB" 

# Load the DiGraph into ArangoDB 
G_nxadb = nxadb.DiGraph(
    name="cit_patents",
    incoming_graph_data=G_nx,
    write_batch_size=50000
)

现在,假设已创建新的 Python 会话。你可以自行决定是在同一台机器还是在其他机器上创建新会话。当你与团队成员合作进行协作开发时,这可能会很有用。

实例化 NetworkX-ArangoDB 图形

通过使用环境变量指定连接凭据并重新实例化 nxadb.DiGraph,可以重新连接到持久图形。提供可选的 read_batch_sizeread_parallelism 参数,以优化数据读取。

图形实例化不会将图形拉入内存,而是建立与持久图形的远程连接。

# Median Time: 0 seconds 

import nx_arangodb as nxadb

os.environ["DATABASE_HOST"] = "https://123.arangodb.cloud:8529"
os.environ["DATABASE_USERNAME"] = "root"
os.environ["DATABASE_PASSWORD"] = "password"
os.environ["DATABASE_NAME"] = "myDB" 

# Connect to the persisted Graph in ArangoDB
# This doesn't pull the graph; You're just establishing a remote connection.
G_nxadb }}{{= nxadb.DiGraph(
     name="cit_patents",
           read_parallelism=15,
           read_batch_size=3000000
)

使用 ArangoDB 运行 cuGraph 算法

通过使用 GPU,您可以依靠相同的算法来获取 ArangoDB 图形的 GPU 表示,其内存占用明显小于 CPU 表示。在提取 ArangoDB 图形后,它被缓存为 NetworkX-cuGraph 图形,这使您能够运行更多算法,而无需再次拉取算法,除非用户明确要求这样做。

# Option 1: Explicit Graph Creation

from nx_arangodb.convert import nxadb_to_nxcg

# Pull the graph from ArangoDB and cache it
# Median Time: 30 seconds
G_nxcg = nxadb_to_nxcg(G_nxadb)

# Median Time: 5 seconds
result = nx.betweenness_centrality(G_nxcg, k=10)
# Option 2 (recommended): On-demand Graph Creation
# This pulls the graph from ArangoDB on the first algorithm call & caches it  

# Median Time: 35 seconds 
result = nx.betweenness_centrality(G_nxadb, k=10)


ArangoDB 中的数据持久性

鉴于在 ArangoDB 中保留 NetworkX 图形的新功能,与不涉及数据库相比,您可以将加载新会话的速度提高 3 倍。

说明 步骤 时间 (秒)
ArangoDB 中不保留数据 0-2 小时 105
ArangoDB 中的数据持久性 5 35
加速   3 倍
表 1. 使用和不使用 ArangoDB 的工作流比较。

在数据上运行多个会话或要求多人在没有ArangoDB的情况下分析相同的数据将给从头开始带来不便。拥有持久性层有助于此工作流程。这使得cuGraph和ArangoDB的组合成为在NetworkX中处理大型图形的关键策略。

将 CRUD 功能与 NetworkX-ArangoDB 结合使用

如果您选择将 NetworkX-ArangoDB 用于 CRUD 功能,则可以使用更多的功能。NetworkX-ArangoDB 十分重视零代码更改,这意味着 NetworkX-ArangoDB 图的 CRUD 接口与 NetworkX 图形相同。

坚持使用 ArangoDB 还可以利用 ArangoDB 的多模型查询语言,Arango 查询语言(AQL)。这是一种统一查询语言,可在一个平台上执行图形遍历、全文搜索、文档检索和键值查找。

import nx_arangodb as nxadb

G_nxadb = nxadb.DiGraph(name="cit_patents") # Connect to ArangoDB 

assert G_nxadb.number_of_nodes() == G_nx.number_of_nodes() 
assert G_nxadb.number_of_edges() == G_nx.number_of_edges() 
assert len(G_nxadb[5526234]) == len(G_nx[5526234])

G_nxadb.nodes[1]["foo"] = "bar"
del G_nxadb.nodes[1]["foo"]

G_nxadb[5526234][4872081]["object"] = {"foo": "bar"}
G_nxadb[5526234][4872081]["object"]["foo"] = "bar!"
del G_nxadb[5526234][4872081]["object"]

G_nxadb.add_edge("A", "B", bar="foo")
G_nxadb["A"]["B"]["bar"] = "foo!"
del G_nxadb.nodes["A"]
del G_nxadb.nodes["B"]

结束语

将 NetworkX Graph API 与 ArangoDB 中的持久性以及 cuGraph 的快速处理相结合,为您提供了一个生产级工作台,用于构建模型和流程。ArangoDB 与 NVIDIA 之间的这种技术集成代表着图形数据库分析的重大演进。

通过在 ArangoDB 中保留持久图形数据,您会发现可以避免手动导出数据或使用内存存储时常见的复杂性和低效性。准确地说,内存存储在某些情况下速度虽然很快,但对于大型图形来说并不理想,因为内存限制,并且在系统崩溃和其他计划外停机期间数据丢失的风险很高。

对于 NetworkX 用户,ArangoDB 提供了一个理想且易于实施的透明持久性层,改变了图形数据的存储和访问方式。现在,您无需离开熟悉的 NetworkX,即可运行大规模图形分析。现有的 ArangoDB 客户还将看到高级图形分析和由 cuGraph 支持的 NetworkX 加速性能的优势。

如需详细了解此强大集成的全部潜力并抢先体验,请参阅 Introducing the ArangoDB NetworkX Persistence 层简介。

 

Tags