Skip to content

Commit

Permalink
Add nvidia jetson xavier agx and apple m2
Browse files Browse the repository at this point in the history
  • Loading branch information
maartenarnst committed Jul 29, 2024
1 parent 5ae7452 commit 4df4eb9
Show file tree
Hide file tree
Showing 8 changed files with 194 additions and 41 deletions.
3 changes: 1 addition & 2 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"image": "ghcr.io/uliegecsm/hwloc-xml-parser/hwloc_xml_parser:latest",
"image": "ghcr.io/uliegecsm/hwloc-xml-parser",
"extensions" : [
"ms-vscode.cmake-tools",
"eamodio.gitlens",
"mhutchie.git-graph",
"ms-azuretools.vscode-docker"
Expand Down
22 changes: 12 additions & 10 deletions .github/workflows/build.image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ on:
- main
paths:
- 'requirements/*'
- 'docker/dockerfile'
pull_request:
branches:
- main
paths:
- 'requirements/*'
- 'docker/dockerfile'

jobs:

set_vars:
set-vars:
uses: ./.github/workflows/set-vars.yml

build-image:
needs: [set_vars]
needs: [set-vars]
runs-on: [ubuntu-latest]
container:
image: docker:latest
Expand All @@ -37,18 +39,18 @@ jobs:
- name: Login to GitHub Container Registry.
uses: docker/login-action@v3
with:
registry: ${{ needs.set_vars.outputs.CI_REGISTRY }}
registry: ${{ needs.set-vars.outputs.CI_REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push.
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true #${{ github.ref == 'refs/heads/main' }}
file: docker/dockerfile
tags: '${{ needs.set_vars.outputs.CI_IMAGE }}:latest'
cache-from: type=registry,ref='${{ needs.set_vars.outputs.CI_IMAGE }}:latest'
cache-to: type=inline
labels: "org.opencontainers.image.source=${{ github.repositoryUrl }}"
platforms: linux/amd64,linux/arm64
push: ${{ github.ref == 'refs/heads/main' }}
file: docker/dockerfile
tags: ${{ needs.set-vars.outputs.CI_IMAGE }}
cache-from: type=registry,ref=${{ needs.set-vars.outputs.CI_IMAGE }}
cache-to: type=inline
labels: "org.opencontainers.image.source=${{ github.repositoryUrl }}"
10 changes: 5 additions & 5 deletions .github/workflows/set-vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@ on:
workflow_call:
outputs:
CI_IMAGE:
value: ${{ jobs.set_vars.outputs.CI_IMAGE }}
value: ${{ jobs.set-vars.outputs.CI_IMAGE }}
CI_REGISTRY:
value: ${{ jobs.set_vars.outputs.CI_REGISTRY }}
value: ${{ jobs.set-vars.outputs.CI_REGISTRY }}

env:
REGISTRY: ghcr.io

jobs:

set_vars:
set-vars:
runs-on: [ubuntu-latest]
outputs:
CI_IMAGE : ${{ steps.common.outputs.CI_IMAGE }}
Expand All @@ -20,5 +20,5 @@ jobs:
- name: Export common variables.
id : common
run : |
echo "CI_IMAGE=${{ env.REGISTRY }}/${{ github.repository }}/hwloc_xml_parser" >> $GITHUB_OUTPUT
echo "CI_REGISTRY=${{ env.REGISTRY }}" >> $GITHUB_OUTPUT
echo "CI_IMAGE=${{ env.REGISTRY }}/${{ github.repository }}" >> $GITHUB_OUTPUT
echo "CI_REGISTRY=${{ env.REGISTRY }}" >> $GITHUB_OUTPUT
10 changes: 5 additions & 5 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ on:
- main

jobs:
set_vars:
set-vars:
uses: ./.github/workflows/set-vars.yml

test:
needs: [set_vars]
needs: [set-vars]
runs-on: [ubuntu-latest]
container:
image: '${{ needs.set_vars.outputs.CI_IMAGE }}:latest'
image: ${{ needs.set-vars.outputs.CI_IMAGE }}
steps:
- name: Checkout code.
uses: actions/checkout@v4
Expand All @@ -26,10 +26,10 @@ jobs:
python -m pytest tests/test_topology.py
install-as-package-and-test:
needs: [set_vars]
needs: [set-vars]
runs-on: [ubuntu-latest]
container:
image: '${{ needs.set_vars.outputs.CI_IMAGE }}:latest'
image: ${{ needs.set-vars.outputs.CI_IMAGE }}
steps:
- name: Install as package.
run : |
Expand Down
4 changes: 2 additions & 2 deletions hwloc_xml_parser/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ def get_num_pus(self) -> int:
@typeguard.typechecked
def all_equal_num_pus_per_core(self) -> bool:
"""
Returns True if all cores have the same number of processing units.
Returns `True` if all cores have the same number of processing units.
"""
return all([core.get_num_pus() == self.cores[0].get_num_pus() for core in self.cores])

Expand Down Expand Up @@ -226,6 +226,6 @@ def get_num_pus(self) -> int:
@typeguard.typechecked
def all_equal_num_pus_per_core(self) -> bool:
"""
Returns True if all cores have the same number of processing units.
Returns `True` if all cores have the same number of processing units.
"""
return all([package.all_equal_num_pus_per_core() for package in self.packages])
34 changes: 34 additions & 0 deletions tests/data/single-apple-m2.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topology SYSTEM "hwloc2.dtd">
<topology version="2.0">
<object type="Machine" os_index="0" cpuset="0x000000ff" complete_cpuset="0x000000ff" allowed_cpuset="0x000000ff" nodeset="0x00000001" complete_nodeset="0x00000001" allowed_nodeset="0x00000001" gp_index="1">
<object type="Package" os_index="0" cpuset="0x000000ff" complete_cpuset="0x000000ff" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="3">
<object type="NUMANode" os_index="0" cpuset="0x000000ff" complete_cpuset="0x000000ff" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="19" local_memory="16763441152">
</object>
<object type="Core" os_index="0" cpuset="0x00000001" complete_cpuset="0x00000001" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="2">
<object type="PU" os_index="0" cpuset="0x00000001" complete_cpuset="0x00000001" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="4"/>
</object>
<object type="Core" os_index="1" cpuset="0x00000002" complete_cpuset="0x00000002" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="5">
<object type="PU" os_index="1" cpuset="0x00000002" complete_cpuset="0x00000002" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="6"/>
</object>
<object type="Core" os_index="2" cpuset="0x00000004" complete_cpuset="0x00000004" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="7">
<object type="PU" os_index="2" cpuset="0x00000004" complete_cpuset="0x00000004" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="8"/>
</object>
<object type="Core" os_index="3" cpuset="0x00000008" complete_cpuset="0x00000008" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="9">
<object type="PU" os_index="3" cpuset="0x00000008" complete_cpuset="0x00000008" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="10"/>
</object>
<object type="Core" os_index="4" cpuset="0x00000010" complete_cpuset="0x00000010" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="11">
<object type="PU" os_index="4" cpuset="0x00000010" complete_cpuset="0x00000010" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="12"/>
</object>
<object type="Core" os_index="5" cpuset="0x00000020" complete_cpuset="0x00000020" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="13">
<object type="PU" os_index="5" cpuset="0x00000020" complete_cpuset="0x00000020" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="14"/>
</object>
<object type="Core" os_index="6" cpuset="0x00000040" complete_cpuset="0x00000040" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="15">
<object type="PU" os_index="6" cpuset="0x00000040" complete_cpuset="0x00000040" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="16"/>
</object>
<object type="Core" os_index="7" cpuset="0x00000080" complete_cpuset="0x00000080" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="17">
<object type="PU" os_index="7" cpuset="0x00000080" complete_cpuset="0x00000080" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="18"/>
</object>
</object>
</object>
</topology>
44 changes: 44 additions & 0 deletions tests/data/single-nvidia-jetson-xavier-agx.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE topology SYSTEM "hwloc2.dtd">
<topology version="2.0">
<object type="Machine" os_index="0" cpuset="0x000000ff" complete_cpuset="0x000000ff" allowed_cpuset="0x000000ff" nodeset="0x00000001" complete_nodeset="0x00000001" allowed_nodeset="0x00000001" gp_index="1">
<object type="NUMANode" os_index="0" cpuset="0x000000ff" complete_cpuset="0x000000ff" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="22" local_memory="15630774272">
</object>
<object type="Package" os_index="0" cpuset="0x00000003" complete_cpuset="0x00000003" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="3">
<info name="CPUModel" value="ARMv8 Processor rev 0 (v8l)"/>
<object type="Core" os_index="0" cpuset="0x00000001" complete_cpuset="0x00000001" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="2">
<object type="PU" os_index="0" cpuset="0x00000001" complete_cpuset="0x00000001" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="4"/>
</object>
<object type="Core" os_index="1" cpuset="0x00000002" complete_cpuset="0x00000002" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="5">
<object type="PU" os_index="1" cpuset="0x00000002" complete_cpuset="0x00000002" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="6"/>
</object>
</object>
<object type="Package" os_index="1" cpuset="0x0000000c" complete_cpuset="0x0000000c" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="8">
<info name="CPUModel" value="ARMv8 Processor rev 0 (v8l)"/>
<object type="Core" os_index="0" cpuset="0x00000004" complete_cpuset="0x00000004" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="7">
<object type="PU" os_index="2" cpuset="0x00000004" complete_cpuset="0x00000004" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="9"/>
</object>
<object type="Core" os_index="1" cpuset="0x00000008" complete_cpuset="0x00000008" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="10">
<object type="PU" os_index="3" cpuset="0x00000008" complete_cpuset="0x00000008" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="11"/>
</object>
</object>
<object type="Package" os_index="2" cpuset="0x00000030" complete_cpuset="0x00000030" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="13">
<info name="CPUModel" value="ARMv8 Processor rev 0 (v8l)"/>
<object type="Core" os_index="0" cpuset="0x00000010" complete_cpuset="0x00000010" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="12">
<object type="PU" os_index="4" cpuset="0x00000010" complete_cpuset="0x00000010" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="14"/>
</object>
<object type="Core" os_index="1" cpuset="0x00000020" complete_cpuset="0x00000020" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="15">
<object type="PU" os_index="5" cpuset="0x00000020" complete_cpuset="0x00000020" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="16"/>
</object>
</object>
<object type="Package" os_index="3" cpuset="0x000000c0" complete_cpuset="0x000000c0" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="18">
<info name="CPUModel" value="ARMv8 Processor rev 0 (v8l)"/>
<object type="Core" os_index="0" cpuset="0x00000040" complete_cpuset="0x00000040" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="17">
<object type="PU" os_index="6" cpuset="0x00000040" complete_cpuset="0x00000040" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="19"/>
</object>
<object type="Core" os_index="1" cpuset="0x00000080" complete_cpuset="0x00000080" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="20">
<object type="PU" os_index="7" cpuset="0x00000080" complete_cpuset="0x00000080" nodeset="0x00000001" complete_nodeset="0x00000001" gp_index="21"/>
</object>
</object>
</object>
</topology>
108 changes: 91 additions & 17 deletions tests/test_topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TestSystemTopology:
def test_parse_single_intel_core_i7_4790(self):
"""
The test reads an `xml` file with the output of `lstopo-no-graphics`
for a single Intel Core i7 4790 machine with the following topology:
for a single `Intel Core i7 4790` machine with the following topology:
.. code-block:: python
Expand Down Expand Up @@ -69,49 +69,57 @@ def test_parse_single_intel_core_i7_4790(self):
assert st.get_num_packages() == 1

# The package has 4 cores.
assert len(st.packages[0].cores) == 4
assert st.packages[0].get_num_cores() == 4
package = st.packages[0]

assert len(package.cores) == 4
assert package.get_num_cores() == 4

# The first core of the package has 2 PUs.
assert len(st.packages[0].cores[0].pus) == 2
assert st.packages[0].cores[0].get_num_pus() == 2
assert len(package.cores[0].pus) == 2
assert package.cores[0].get_num_pus() == 2

# The first PU of the second core of the package has OS index 1 and logical index 2.
assert st.packages[0].cores[1].pus[0].os_index == 1
assert st.packages[0].cores[1].pus[0].logical_index == 2
assert package.cores[1].pus[0].os_index == 1
assert package.cores[1].pus[0].logical_index == 2

# Repeat the last assertions, but using this time the generator returned by the
# method :py:meth:`hwloc_xml_parser.topology.SystemTopology.recurse_cores`.
gen_cores = st.recurse_cores()
_ = next(gen_cores)
second_core = next(gen_cores)
assert second_core.pus[0].os_index == 1
assert second_core.pus[0].logical_index == 2

# Repeat the last assertions, but using this time the generator returned by the
# method :py:meth:`hwloc_xml_parser.topology.SystemTopology.recurse_pus`.
gen_pus = st.recurse_pus()
_ = next(gen_pus)
_ = next(gen_pus)
third_pu = next(gen_pus)
assert third_pu.os_index == 1
assert third_pu.logical_index == 2

# The second PU of the second core of the package has OS index 5 and logical index 3.
assert st.packages[0].cores[1].pus[1].os_index == 5
assert st.packages[0].cores[1].pus[1].logical_index == 3
assert package.cores[1].pus[1].os_index == 5
assert package.cores[1].pus[1].logical_index == 3

# All cores of the package have 2 PUs.
assert st.packages[0].all_equal_num_pus_per_core()
assert package.all_equal_num_pus_per_core()

# The machine has 8 PUs in total.
assert st.get_num_cores() == 4

# The machine has 8 PUs in total.
assert st.get_num_pus() == 8
assert st.packages[0].get_num_pus() == 8
assert package.get_num_pus() == 8

# All cores of the machine have the same number of PUs.
assert st.all_equal_num_pus_per_core()

def test_parse_dual_intel_xeon_gold_6126(self):
"""
The test reads an `xml` file with the output of `lstopo-no-graphics`
for a dual Intel Xeon Gold 6126 machine with the following topology:
for a dual `Intel Xeon Gold 6126` machine with the following topology:
.. code-block:: python
Expand Down Expand Up @@ -232,15 +240,17 @@ def test_parse_dual_intel_xeon_gold_6126(self):
assert st.get_num_packages() == 2

# The first package has 12 cores.
assert len(st.packages[0].cores) == 12
assert st.packages[0].get_num_cores() == 12
first_package = st.packages[0]

assert len(first_package.cores) == 12
assert first_package.get_num_cores() == 12

# The first core of the first package has 2 PUs.
assert len(st.packages[0].cores[0].pus) == 2
assert st.packages[0].cores[0].get_num_pus() == 2
assert len(first_package.cores[0].pus) == 2
assert first_package.cores[0].get_num_pus() == 2

# All cores of the first package have 2 PUs.
assert st.packages[0].all_equal_num_pus_per_core()
assert first_package.all_equal_num_pus_per_core()

# The machine has 24 cores in total.
assert st.get_num_cores() == 24
Expand All @@ -250,3 +260,67 @@ def test_parse_dual_intel_xeon_gold_6126(self):

# All cores of the machine have the same number of PUs.
assert st.all_equal_num_pus_per_core()

def test_parse_single_nvidia_jetson_xavier_agx(self):
"""
The test reads an `xml` file with the output of `lstopo-no-graphics`
for a single `Nvidia Jetson Xavier AGX` machine.
"""
hwloc_calc_values = [
b'0,1,2,3',
b'0,1,2,3,4,5,6,7',
b'0,1,2,3,4,5,6,7'
]

with unittest.mock.patch(
target = 'subprocess.check_output',
side_effect = hwloc_calc_values,
):
st = SystemTopology(load = False)
st._parse(filename = 'tests/data/single-nvidia-jetson-xavier-agx.xml')

# There are 4 packages.
# This is how `hwloc` reports it. Physically, there is a single package, with 4 clusters of 2 cores each.
#
# See also:
# - https://www.anandtech.com/show/13584/nvidia-xavier-agx-hands-on-carmel-and-more
assert st.get_num_packages() == 4

# The machine has 8 cores in total.
assert st.get_num_cores() == 8

# The machine has 8 PUs in total.
assert st.get_num_pus() == 8

# All cores of the machine have the same number of PUs.
assert st.all_equal_num_pus_per_core()

def test_parse_single_apple_m2(self):
"""
The test reads an `xml` file with the output of `lstopo-no-graphics`
for a single `Apple M2` machine.
"""
hwloc_calc_values = [
b'0',
b'0,1,2,3,4,5,6,7',
b'0,1,2,3,4,5,6,7'
]

with unittest.mock.patch(
target = 'subprocess.check_output',
side_effect = hwloc_calc_values,
):
st = SystemTopology(load = False)
st._parse(filename = 'tests/data/single-apple-m2.xml')

# The machine has 1 package.
assert st.get_num_packages() == 1

# The machine has 8 cores in total.
assert st.get_num_cores() == 8

# The machine has 8 PUs in total.
assert st.get_num_pus() == 8

# All cores of the machine have the same number of PUs.
assert st.all_equal_num_pus_per_core()

0 comments on commit 4df4eb9

Please sign in to comment.