mirror of
https://github.com/JuliaFEM/JuliaFEM.jl.git
synced 2026-09-23 02:59:52 +00:00
7f9e382a40
New 203-line GPU-only demonstration (simplified without MPI complexity): Setup and validation (lines 1-52): - Checks for CUDA availability, exits if not found - Reports GPU model and memory - Sets up problem: 10000 nodes, 1000 elements - Type-stable data: nodes (Float64), connectivity (Int), E, ν GPU kernel (lines 54-120): - assemble_element_kernel! for CUDA - Type-stable: Float64, Int32, CuDeviceMatrix/Vector - No allocations in kernel - Computes simplified assembly: K_local = E * (1-ν²) Execution (lines 122-170): - Transfers data to GPU (nodes, connectivity) - Reports bytes transferred - Launches kernel with thread blocks - Transfers results back from GPU Verification (lines 172-203): - Compares computed vs expected values - Reports success/failure - Key achievements summary: * Type-stable kernel compiled * Fast GPU memory transfer (typed arrays) * Zero allocations in kernel - Why it matters: Dict-based storage CANNOT compile for GPU - Conclusion: type stability required for modern HPC Purpose: Simpler test than full MPI version, focuses on GPU capability Run: julia demos/gpu_only_demo.jl (requires CUDA GPU)
204 lines
5.4 KiB
Julia
204 lines
5.4 KiB
Julia
#!/usr/bin/env julia
|
||
#
|
||
# GPU-Only Demonstration (No MPI Required)
|
||
#
|
||
# Demonstrates that type-stable field data can execute on real CUDA GPU.
|
||
# Simpler than full GPU+MPI demo - just shows GPU capability.
|
||
#
|
||
|
||
using LinearAlgebra
|
||
|
||
println("="^70)
|
||
println("GPU Type-Stable Kernel Demonstration")
|
||
println("="^70)
|
||
println()
|
||
|
||
# Try to load CUDA
|
||
CUDA_AVAILABLE = false
|
||
try
|
||
@eval using CUDA
|
||
if CUDA.functional()
|
||
global CUDA_AVAILABLE = true
|
||
println("✅ CUDA GPU detected: $(CUDA.name(CUDA.device()))")
|
||
println(" Memory: $(CUDA.totalmem(CUDA.device()) ÷ 10^9) GB")
|
||
println()
|
||
else
|
||
println("❌ CUDA.jl loaded but no functional GPU detected")
|
||
exit(1)
|
||
end
|
||
catch e
|
||
println("❌ CUDA.jl not available: $e")
|
||
println(" Install with: using Pkg; Pkg.add(\"CUDA\")")
|
||
exit(1)
|
||
end
|
||
|
||
println("="^70)
|
||
println("Demonstration: Type-Stable Assembly Kernel")
|
||
println("="^70)
|
||
println()
|
||
|
||
# Problem setup
|
||
n_nodes = 10000
|
||
n_elements = 1000
|
||
|
||
println("Setup:")
|
||
println(" Nodes: $n_nodes")
|
||
println(" Elements: $n_elements")
|
||
println()
|
||
|
||
# Type-stable data structures
|
||
nodes = rand(Float64, 3, n_nodes)
|
||
connectivity = rand(1:n_nodes, 8, n_elements)
|
||
E = 210e3 # Young's modulus
|
||
ν = 0.3 # Poisson's ratio
|
||
|
||
println("Data types (type-stable):")
|
||
println(" nodes: $(typeof(nodes))")
|
||
println(" connectivity: $(typeof(connectivity))")
|
||
println(" E: $(typeof(E))")
|
||
println(" ν: $(typeof(ν))")
|
||
println()
|
||
|
||
# Define GPU kernel
|
||
function assemble_element_kernel!(
|
||
K_elements::CuDeviceMatrix{Float64},
|
||
nodes::CuDeviceMatrix{Float64},
|
||
connectivity::CuDeviceMatrix{Int32},
|
||
E::Float64,
|
||
ν::Float64,
|
||
n_elements::Int32
|
||
)
|
||
# GPU thread indexing
|
||
idx = (blockIdx().x - 1) * blockDim().x + threadIdx().x
|
||
|
||
if idx <= n_elements
|
||
# Type-stable access to element data
|
||
# In real FEM: would integrate over Gauss points
|
||
# Here: simplified computation to demonstrate GPU execution
|
||
|
||
# Mock stiffness calculation
|
||
K_local = E * (1 - ν^2)
|
||
|
||
# Store result
|
||
K_elements[idx, 1] = K_local
|
||
end
|
||
|
||
return nothing
|
||
end
|
||
|
||
println("="^70)
|
||
println("Step 1: Transfer Data to GPU")
|
||
println("="^70)
|
||
println()
|
||
|
||
# Calculate sizes
|
||
nodes_bytes = sizeof(nodes)
|
||
conn_bytes = sizeof(connectivity)
|
||
total_bytes = nodes_bytes + conn_bytes
|
||
|
||
println("Transferring to GPU:")
|
||
println(" nodes: $(nodes_bytes ÷ 1024) KB")
|
||
println(" connectivity: $(conn_bytes ÷ 1024) KB")
|
||
println(" Total: $(total_bytes ÷ 1024) KB")
|
||
println()
|
||
|
||
# Transfer to GPU
|
||
d_nodes = CuArray(nodes)
|
||
d_connectivity = CuArray(Int32.(connectivity))
|
||
d_K_elements = CUDA.zeros(Float64, n_elements, 64)
|
||
|
||
println("✅ Data on GPU")
|
||
println()
|
||
|
||
println("="^70)
|
||
println("Step 2: Launch GPU Kernel")
|
||
println("="^70)
|
||
println()
|
||
|
||
# Kernel launch configuration
|
||
threads_per_block = 256
|
||
blocks = cld(n_elements, threads_per_block)
|
||
|
||
println("Kernel configuration:")
|
||
println(" Threads per block: $threads_per_block")
|
||
println(" Blocks: $blocks")
|
||
println(" Total threads: $(blocks * threads_per_block)")
|
||
println()
|
||
|
||
println("Launching kernel...")
|
||
@cuda threads = threads_per_block blocks = blocks assemble_element_kernel!(
|
||
d_K_elements, d_nodes, d_connectivity, E, ν, Int32(n_elements)
|
||
)
|
||
|
||
# Wait for completion
|
||
CUDA.synchronize()
|
||
|
||
println("✅ Kernel executed successfully")
|
||
println()
|
||
|
||
println("="^70)
|
||
println("Step 3: Transfer Results from GPU")
|
||
println("="^70)
|
||
println()
|
||
|
||
K_elements = Array(d_K_elements)
|
||
result_bytes = sizeof(K_elements)
|
||
|
||
println("Transferred from GPU:")
|
||
println(" Results: $(result_bytes ÷ 1024) KB")
|
||
println()
|
||
|
||
println("="^70)
|
||
println("Step 4: Verify Results")
|
||
println("="^70)
|
||
println()
|
||
|
||
expected_value = E * (1 - ν^2)
|
||
actual_values = K_elements[:, 1]
|
||
all_match = all(abs.(actual_values .- expected_value) .< 1e-10)
|
||
|
||
println("Verification:")
|
||
println(" Expected value: $expected_value")
|
||
println(" First result: $(actual_values[1])")
|
||
println(" All elements match: $(all_match ? "✅" : "❌")")
|
||
println()
|
||
|
||
if all_match
|
||
println("="^70)
|
||
println("✅ SUCCESS: Type-Stable GPU Kernel Executed Correctly")
|
||
println("="^70)
|
||
println()
|
||
println("Key Achievements:")
|
||
println()
|
||
println("1. Type-stable kernel compiled for GPU")
|
||
println(" - All parameters have concrete types (Float64, Int32)")
|
||
println(" - No Dict{String,Any} or runtime dispatch")
|
||
println(" - Compiler generated optimized GPU machine code")
|
||
println()
|
||
println("2. Fast GPU memory transfer")
|
||
println(" - Typed arrays transferred as contiguous buffers")
|
||
println(" - No serialization overhead")
|
||
println(" - Same pattern works for MPI communication")
|
||
println()
|
||
println("3. Zero allocations in kernel")
|
||
println(" - All arrays pre-allocated")
|
||
println(" - In-place operations only")
|
||
println(" - Required for GPU execution")
|
||
println()
|
||
println("Why This Matters:")
|
||
println()
|
||
println("• Dict{String,Any} field storage CANNOT compile for GPU")
|
||
println(" - Compiler error: cannot determine types")
|
||
println(" - Would prevent any GPU acceleration")
|
||
println()
|
||
println("• Type-stable storage (Matrix{Float64}) works everywhere:")
|
||
println(" - CPU: 9-92× faster (measured)")
|
||
println(" - GPU: Enables execution (demonstrated)")
|
||
println(" - MPI: Fast transfers (same pattern)")
|
||
println()
|
||
println("Conclusion: Type stability is not optional for modern HPC")
|
||
println("="^70)
|
||
else
|
||
println("❌ FAILED: Results don't match expected values")
|
||
end
|