Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add GPU support for mac, multi gpu for linux #7

Merged
merged 11 commits into from
Apr 10, 2023

Conversation

triarius
Copy link
Contributor

@triarius triarius commented Apr 8, 2023

Used system_profiler to obtain the GPU name in macOS. I've only tested it on a M1 MacBook Air, it givs the output "Apple M1".

For linux, I dug a little into the data that lspci gives back instead of just presenting the entire line. On my machine, it previously gave:

GPU: 01:00.0 3D controller: NVIDIA Corporation GA107M [GeForce RTX 3050 Ti Mobile] (rev a1)

But now it is just

GPU: GA107M [GeForce RTX 3050 Ti Mobile]

which I think is more in line with what users expect.

Also, in both macOS and linux, multiple gpus will be returned if the respective commands detect them.

You can see this in the screenshot from my system where the new behaviour is on top, and the old is below.
2023-04-08T10:33:48,344141774+10:00

Some implementations notes

I used serde_json to parse the output of system_profiler, but a regex for lspci -mm. This could be improved by finding an approproite parser for the ouput of lspci -mm, but it's a mixture of quoted and unquoted space seperated fields. Perhaps some csv style parser will work, but I didn't try too hard to find one. According to the man, the fields are quoted "if necessary". So, the regex implementation will break if some of the quoted fields are not quoted. However, I think we can ship this and fix it if we find reports of failure.

To allow mutiple GPUs, I collected the gpu names into a vector and then joined them with a newline separator. There is no need to allocate that vecotor, but I think it's a microoptimisation to improve it. It's highly likely that the number of GPUs is one or two, so improveing this is not going to yeild a massive performance improvement.

@nidnogg nidnogg linked an issue Apr 8, 2023 that may be closed by this pull request
@nidnogg nidnogg self-requested a review April 8, 2023 04:32
@nidnogg
Copy link
Owner

nidnogg commented Apr 8, 2023

Heya! I wasn't aware that lscpi provided machine-readable input, nice catch. This should prevent a fair bit of edge cases. I agree with the expected output, especially on Linux.

Regarding macOS, for m1 machines I have seen just Apple M1 pop up before, and I think it might be the suitable output, after all.

I left some comments in the PR review, mostly out of curiosity. I'll be testing the changes out on my machines and seeing how it goes. And as always, thanks for chipping in! ✌️ Hoping to merge these soon.


lazy_static! {
static ref GPU_RE: Regex =
Regex::new(r#"^\S+? "(VGA|3D|Display).*?" ".*?" "(?P<gpu>.*?)""#).unwrap();
Copy link
Owner

@nidnogg nidnogg Apr 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking unwrap() here might not be the best option - even though it does seem unlikely to fail since the regex has been tested already. If it does, however, omitting routines dependent on GPU_RE could be an option.

Copy link
Contributor Author

@triarius triarius Apr 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Generally, I too am averse to unwrap() - the docs discourage its use, although most people in the rust community don't seem to heed this.

However, in this case, the error will only occur if the regex: r#"^\S+? "(VGA|3D|Display).*?" ".*?" "(?P<gpu>.*?)""# is not well-defined, not if there is an error when matching any particular string. Because the regex is a constant string, the value of Regex::new(...) will either always be an Err, or always be an Ok. There is no variation in runtime behaviour. So pushing the error handling down to the consumers of GPU_RE at runtime is a waste. (Incidentally, the fact that the regex is constant is also why I'm using the lazy_static macro to ensure it's only compiled once.)

Ideally, this is something that could be detected at compile time, but it might be outside the design of the compiler to check this. I think this is the next best thing: any attempt to use this module will break, even if no methods from the module are invoked. One way to make this more robust is to have a test that asserts that the regex does not panic. I suspect any test that has use crate::scanner in it will achieve this. I think I might verify this and add one.

LMK what you think.

@triarius triarius force-pushed the triarius/gpu-mac-linux branch from 9c729a1 to 3c537e1 Compare April 8, 2023 14:36
@triarius
Copy link
Contributor Author

triarius commented Apr 10, 2023

@nidnogg I've verified that the tests fail if regex is not well defined:

🕙 15:39:07 ❯ cargo test
   Compiling zeitfetch v0.1.6 (/home/narthana/devel/triarius/zeitfetch)
    Finished test [unoptimized + debuginfo] target(s) in 0.50s
     Running unittests src/main.rs (target/debug/deps/zeitfetch-dfb92a9cf192c76e)

running 3 tests
test scanner::tests::gpu_regex_empty ... FAILED
test scanner::tests::gpu_regex_nvidia ... FAILED
test scanner::tests::gpu_regex_not_gpu ... FAILED

failures:

---- scanner::tests::gpu_regex_empty stdout ----
thread 'scanner::tests::gpu_regex_empty' panicked at 'called `Result::unwrap()` on an `Err` value: Syntax(
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
regex parse error:
    ^\S+? "(VGA|3D|Display.*?" ".*?" "(?P<gpu>.*?)"
           ^
error: unclosed group
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
)', src/scanner.rs:26:74
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

---- scanner::tests::gpu_regex_nvidia stdout ----
thread 'scanner::tests::gpu_regex_nvidia' panicked at 'Once instance has previously been poisoned', /home/narthana/.local/share/cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:30:16

---- scanner::tests::gpu_regex_not_gpu stdout ----
thread 'scanner::tests::gpu_regex_not_gpu' panicked at 'Once instance has previously been poisoned', /home/narthana/.local/share/cargo/registry/src/github.jparrowsec.cn-1ecc6299db9ec823/lazy_static-1.4.0/src/inline_lazy.rs:30:16


failures:
    scanner::tests::gpu_regex_empty
    scanner::tests::gpu_regex_not_gpu
    scanner::tests::gpu_regex_nvidia

test result: FAILED. 0 passed; 3 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

The GitHub actions won't run on this repo, but they seem to work on my fork: https://github.com/triarius/zeitfetch/actions/runs/4645677080.

They will probably start to run once you've merged this in.

@nidnogg
Copy link
Owner

nidnogg commented Apr 10, 2023

@triarius this looks pretty much good to. There's just one comment I'd like some clarification on - it's the SPDisplay used as a name for a few structs. I'm not sure what SP stands for there. Could you rename structs and consts using that name? Other than that, looks good to me!

@triarius triarius force-pushed the triarius/gpu-mac-linux branch from 86b3a87 to 930ea00 Compare April 10, 2023 14:27
@triarius
Copy link
Contributor Author

triarius commented Apr 10, 2023

I'm not sure what SP stands for there. Could you rename structs and consts using that name?

@nidnogg The SP initialism is for the macOS command system_profiler. I guess I could name them something else, but I think it's best to keep the connection in the names. I've added some comments about it, though. And I've included some realistic test data, so the format of the output is recorded in the tests.

@nidnogg nidnogg merged commit 46c8f0c into nidnogg:main Apr 10, 2023
@triarius triarius deleted the triarius/gpu-mac-linux branch April 10, 2023 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

macOS Display detection for GPU row
2 participants