@@ -617,7 +617,8 @@ function Base.:*(A::MatrixMPI{T,AM}, x::VectorMPI{T,AV}) where {T,AM,AV}
617617 # Matrix is on CPU - compute on CPU, then copy to GPU if needed
618618 y_local_cpu = Vector {T} (undef, local_rows)
619619 LinearAlgebra. mul! (y_local_cpu, A. A, plan. gathered_cpu)
620- y_v = _create_output_like (x. v, y_local_cpu)
620+ # Copy to GPU if input was GPU
621+ y_v = x. v isa Vector ? y_local_cpu : copyto! (similar (x. v, local_rows), y_local_cpu)
621622 else
622623 # Matrix is on GPU - use GPU gathered buffer directly
623624 y_v = similar (A. A, local_rows)
@@ -1206,8 +1207,8 @@ function Base.:*(At::Transpose{T,<:MatrixMPI{T}}, x::VectorMPI{T,AV}) where {T,A
12061207 my_col_end = A. col_partition[rank+ 2 ] - 1
12071208 local_result_cpu = full_result[my_col_start: my_col_end]
12081209
1209- # Create output with same storage type as input
1210- local_result = _create_output_like ( x. v, local_result_cpu)
1210+ # Copy to GPU if input was GPU
1211+ local_result = x . v isa Vector ? local_result_cpu : copyto! ( similar ( x. v, length (local_result_cpu)) , local_result_cpu)
12111212
12121213 # Create result vector (partition is immutable, no need to copy)
12131214 y = VectorMPI {T,AV} (
@@ -1470,6 +1471,11 @@ end
14701471# DenseRepartitionPlan: Repartition a MatrixMPI to a new row partition
14711472# ============================================================================
14721473
1474+ # Helper to get CPU copy of matrix data (no-op for CPU, copy for GPU)
1475+ # Used for MPI communication which always requires CPU buffers
1476+ _ensure_cpu (M:: Matrix ) = M
1477+ _ensure_cpu (M:: AbstractMatrix ) = Array (M)
1478+
14731479"""
14741480 DenseRepartitionPlan{T}
14751481
@@ -1631,28 +1637,31 @@ function DenseRepartitionPlan(A::MatrixMPI{T}, p::Vector{Int}) where T
16311637end
16321638
16331639"""
1634- execute_plan!(plan::DenseRepartitionPlan{T}, A::MatrixMPI{T}) where T
1640+ execute_plan!(plan::DenseRepartitionPlan{T}, A::MatrixMPI{T,AM }) where {T,AM}
16351641
16361642Execute a dense repartition plan to redistribute rows from A to a new partition.
1637- Returns a new MatrixMPI with the target row partition.
1643+ Returns a new MatrixMPI with the target row partition, preserving the array type (CPU/GPU) .
16381644"""
1639- function execute_plan! (plan:: DenseRepartitionPlan{T} , A:: MatrixMPI{T} ) where T
1645+ function execute_plan! (plan:: DenseRepartitionPlan{T} , A:: MatrixMPI{T,AM } ) where {T,AM}
16401646 comm = MPI. COMM_WORLD
16411647
1642- # Allocate result
1643- result_A = Matrix {T} (undef, plan. result_local_nrows, plan. ncols)
1648+ # Get CPU version of input for MPI operations
1649+ A_cpu = _ensure_cpu (A. A)
1650+
1651+ # Allocate CPU result buffer (MPI requires CPU)
1652+ result_cpu = Matrix {T} (undef, plan. result_local_nrows, plan. ncols)
16441653
1645- # Step 1: Local copy
1654+ # Step 1: Local copy (from CPU staging)
16461655 if ! isempty (plan. local_src_range) && ! isempty (plan. local_dst_range)
1647- result_A [plan. local_dst_range, :] = A . A [plan. local_src_range, :]
1656+ result_cpu [plan. local_dst_range, :] = A_cpu [plan. local_src_range, :]
16481657 end
16491658
1650- # Step 2: Fill send buffers and send
1659+ # Step 2: Fill send buffers and send (from CPU staging)
16511660 @inbounds for i in eachindex (plan. send_rank_ids)
16521661 r = plan. send_rank_ids[i]
16531662 row_range = plan. send_row_ranges[i]
16541663 buf = plan. send_bufs[i]
1655- buf .= @view A . A [row_range, :]
1664+ buf .= @view A_cpu [row_range, :]
16561665 plan. send_reqs[i] = MPI. Isend (vec (buf), comm; dest= r, tag= 93 )
16571666 end
16581667
@@ -1667,12 +1676,15 @@ function execute_plan!(plan::DenseRepartitionPlan{T}, A::MatrixMPI{T}) where T
16671676 @inbounds for i in eachindex (plan. recv_rank_ids)
16681677 dst_range = plan. recv_dst_ranges[i]
16691678 buf = plan. recv_bufs[i]
1670- result_A [dst_range, :] = buf
1679+ result_cpu [dst_range, :] = buf
16711680 end
16721681
16731682 MPI. Waitall (plan. send_reqs)
16741683
1675- return MatrixMPI {T} (plan. result_structural_hash, plan. result_row_partition, plan. result_col_partition, result_A)
1684+ # Copy result back to target array type (GPU if input was GPU)
1685+ result_A = A. A isa Matrix ? result_cpu : copyto! (similar (A. A, size (result_cpu)... ), result_cpu)
1686+
1687+ return MatrixMPI {T,typeof(result_A)} (plan. result_structural_hash, plan. result_row_partition, plan. result_col_partition, result_A)
16761688end
16771689
16781690"""
0 commit comments