impl CudaSimdAnalyzer {
const IGNORED_DIRS: &'static [&'static str] = &[
".venv", "venv", "node_modules", "target", ".git", "__pycache__",
".tox", ".nox", "dist", "build", ".eggs", "*.egg-info",
".mypy_cache", ".pytest_cache", ".cargo", "vendor",
];
fn should_skip_path(path: &Path) -> bool {
for component in path.components() {
if let std::path::Component::Normal(name) = component {
let name_str = name.to_string_lossy();
for ignored in Self::IGNORED_DIRS {
if name_str == *ignored || name_str.ends_with(".egg-info") {
return true;
}
}
}
}
false
}
fn analyze_directory(
&self,
path: &Path,
defects: &mut Vec<DetectedDefect>,
cuda_files: &mut usize,
simd_files: &mut usize,
wgpu_files: &mut usize,
files_analyzed: &mut usize,
barrier_safety: &mut BarrierSafetyResult,
coalescing: &mut CoalescingResult,
) -> anyhow::Result<()> {
for entry in walkdir::WalkDir::new(path)
.follow_links(true)
.into_iter()
.filter_entry(|e| !Self::should_skip_path(e.path()))
.filter_map(Result::ok)
{
let file_path = entry.path();
if file_path.is_file() {
if let Some(ext) = file_path.extension() {
let ext_str = ext.to_string_lossy().to_lowercase();
if matches!(
ext_str.as_str(),
"cu" | "cuh" | "ptx" | "rs" | "wgsl" | "c" | "cpp" | "h" | "hpp"
) {
if let Ok(analysis) = self.analyze_file(file_path) {
*files_analyzed += 1;
*cuda_files += analysis.cuda_files;
*simd_files += analysis.simd_files;
*wgpu_files += analysis.wgpu_files;
defects.extend(analysis.defects);
barrier_safety.total_barriers += analysis.barrier_safety.total_barriers;
barrier_safety.safe_barriers += analysis.barrier_safety.safe_barriers;
barrier_safety.unsafe_barriers.extend(analysis.barrier_safety.unsafe_barriers);
coalescing.total_operations += analysis.coalescing.total_operations;
coalescing.coalesced_operations += analysis.coalescing.coalesced_operations;
coalescing.problematic_accesses.extend(analysis.coalescing.problematic_accesses);
}
}
}
}
}
if barrier_safety.total_barriers > 0 {
barrier_safety.safety_score =
barrier_safety.safe_barriers as f64 / barrier_safety.total_barriers as f64;
}
if coalescing.total_operations > 0 {
coalescing.efficiency =
coalescing.coalesced_operations as f64 / coalescing.total_operations as f64;
}
Ok(())
}
fn analyze_file(&self, path: &Path) -> anyhow::Result<FileAnalysis> {
let content = std::fs::read_to_string(path)?;
let ext = path
.extension()
.map(|e| e.to_string_lossy().to_lowercase())
.unwrap_or_default();
let mut analysis = FileAnalysis::default();
match ext.as_str() {
"cu" | "cuh" | "ptx" => {
analysis.cuda_files = 1;
self.analyze_cuda_content(&content, path, &mut analysis);
}
"wgsl" => {
analysis.wgpu_files = 1;
self.analyze_wgpu_content(&content, path, &mut analysis);
}
"rs" => {
if content.contains("std::arch::") || content.contains("core::arch::") {
analysis.simd_files = 1;
self.analyze_simd_content(&content, path, &mut analysis);
}
if content.contains("wgpu::")
|| content.contains("@compute")
|| content.contains("@workgroup_size")
{
analysis.wgpu_files = 1;
self.analyze_wgpu_content(&content, path, &mut analysis);
}
}
"c" | "cpp" | "h" | "hpp" => {
if content.contains("immintrin.h")
|| content.contains(concat!("_mm", "256_"))
|| content.contains(concat!("_mm", "512_"))
|| content.contains("arm_neon.h")
{
analysis.simd_files = 1;
self.analyze_simd_content(&content, path, &mut analysis);
}
}
_ => {}
}
Ok(analysis)
}
}