You trained a 50 GB model on your workstation. You rented a cloud GPU server with enough memory to run it. You kick off an upload, watch the terminal settle at Transfer rate: 200 KB/s, do the math, and realize the copy will land sometime next week. That is the moment most people go looking for a better way to transfer large files gpu server side, and it is where this guide starts.
Moving a trained model is not the same as uploading a photo. The moment you decide to upload ai model to cloud infrastructure, three things work against you: your connection has a hard ceiling, a single stalled request can kill the whole transfer, and most default tools copy over one connection when your link could carry several. Pick the wrong tool and a job that should take twenty minutes drags on for a day.
The fix is mostly about method, not money. This guide walks through five ways to get a model onto a GPU server, from a plain SSH copy to a direct pull out of cloud storage. You will see which one fits your situation, roughly how fast each runs, and the tuning tricks that shave real time off a big upload. Everything here scales from a 10 GB checkpoint to models north of 500 GB.
Also Read: How to Right-Size GPU Instances and Stop Overpaying in 2026
Why large model transfers to a GPU server are tricky
Four things make model transfers harder than they look.
First, your connection has a ceiling. Most cloud uploads run somewhere between 100 and 500 Mbps, which is roughly 12 to 60 MB per second in practice. A 100 GB model at 50 MB/s takes a little over half an hour, and that is the good case. If the link drops at the halfway mark, a naive tool starts again from zero.
Second, long single requests time out. Push a 100 GB file through a plain HTTP upload and a stall of a few minutes can end the session with nothing to show for it. SSH-based tools behave better here because they can pick up where they left off.
Third, one connection rarely uses your full capacity. A single stream tops out at single-stream speed. Your server and your ISP may happily carry four or eight streams at once, but the default tools never ask for them.
Fourth, you have to prove the file arrived intact. After moving 100 GB, how do you know a bit did not flip along the way? A checksum answers that, and it costs a few minutes you should plan for.
Five strategies cover almost every case: scp for simplicity, rsync for smart resumption, parallel transfers for raw speed, a direct pull from cloud storage such as S3, and, for anyone who prefers a window over a terminal, SFTP. Which one you reach for depends on where the model lives and how big it is.
Also Read: Hidden Cloud GPU Costs That Are Secretly Draining Your Budget in 2026
Before you start: a quick prerequisite check
Five quick checks save you from a failed transfer an hour in.
Confirm you can reach the server over SSH:
| ssh -v user@your-gpu-server.com |
If that connects, scp and rsync will work too.
Check free disk on the server before you send anything:
| ssh user@your-gpu-server.com “df -h / | grep -v Filesystem” |
The model, the operating system, and some working room all have to fit. If the disk is already 90 percent full, add a volume or pick a different partition.
Measure your real upload speed:
| speedtest-cli |
Note the upload number in Mbps. Actual transfers land at about 80 to 90 percent of that once you account for overhead, so treat it as a ceiling, not a promise.
| ssh-keygen -t ed25519ssh-copy-id -i ~/.ssh/id_ed25519.pub user@your-gpu-server.com |
Keys authenticate faster and are safer than typing a password on every connection.
Know exactly what you are sending:
| ls -lh /path/to/model.pthdu -sh /path/to/model/ |
The size decides the method. A 4 GB checkpoint and a 400 GB shard set are not the same job.
Also Read: NVMe Storage for Cloud GPU: Why It Matters for AI Workloads in 2026
Method 1: SCP, simple and best for small to medium files
SCP is the tool most people already know, and for a quick job it is the right call. It ships with SSH, runs over the same encrypted connection, and needs exactly one command. When you scp large files cloud gpu servers can accept them straight away, with no setup beyond working SSH access.
Copy a single file:
| scp /path/to/model.pth user@gpu-server.com:/models/model.pth |
You get a progress bar with speed and an ETA. To send a whole folder, add -r:
| scp -r /path/to/model_folder/ user@gpu-server.com:/models/model_folder/ |
Pulling a model back the other way is the same command with the arguments reversed:
| scp -r user@gpu-server.com:/models/model_folder/ /local/path/ |
SCP also has a compression flag, -C, but think before you use it:
| scp -C /path/to/model.pth user@gpu-server.com:/models/model.pth |
Compression helps for text-like formats. For a PyTorch .pth file, which is already a compressed archive, the CPU cost usually outweighs any saving.
Here is the real limitation. SCP has no resume. If a 100 GB copy dies at 99 percent, you start over from the beginning. That single fact is why it is a poor fit for very large models on a shaky connection.
A quick way to estimate time: 100 Mbps is about 12.5 MB/s, so a 50 GB file takes roughly 50,000 MB divided by 12.5, or about 4,000 seconds. That is a little over an hour, not the multi-day figure a stalled 200 KB/s session would suggest. Halve your speed and you double the wait.
Reach for scp when the file is under about 10 GB, the transfer is a one-off, and your connection is steady. Past that, the tools below earn their extra typing.
Also Read: Metered vs Unmetered Bandwidth: The Hidden Cost Most Businesses Discover Too Late
Method 2: rsync, smart resumption and the default I reach for
If I had to move one model with one tool, it would be rsync. It only sends what is missing, it resumes cleanly after a drop, and it keeps two directories in sync without re-copying files that already match. For keeping rsync gpu server files aligned between your machine and the server, nothing else in this list is as forgiving.
Install it if your machine does not have it:
| # macOSbrew install rsync# Debian or Ubuntu (usually already present)sudo apt-get install rsync# Windows, through WSLwsl sudo apt-get install rsync |
A basic transfer:
| rsync -avz /path/to/model.pth user@gpu-server.com:/models/model.pth |
The flags: -a preserves permissions and timestamps, -v prints progress, -z compresses in transit. For a whole model directory:
| rsync -avz /path/to/model_folder/ user@gpu-server.com:/models/model_folder/ |
Watch the trailing slash on the source. With it, rsync copies the contents of the folder. Without it, you end up with model_folder/model_folder/ on the server.
The flag that matters most for big files is –partial:
| rsync -avz –partial /path/to/model.pth user@gpu-server.com:/models/model.pth |
It keeps the half-transferred file on disk, so a dropped connection resumes instead of restarting. On a 200 GB upload over a home connection, that one flag is the difference between annoying and impossible.
A few options worth knowing:
| # See what would move, and how much, without sending anythingrsync -avz –dry-run /path/to/model.pth user@gpu-server.com:/models/model.pth # Skip junk that bloats the transferrsync -avz –exclude=’*.tmp’ –exclude=’cache/’ /path/to/model/ user@gpu-server.com:/models/ # Cap the rate so you do not starve everything else on your linersync -avz –bwlimit=50M /path/to/model.pth user@gpu-server.com:/models/model.pth |
One caveat on -z. Compression in transit helps text and uncompressed data. Model weights are usually already compressed, so -z can burn CPU for almost no gain, and on a fast link it can even slow you down. Test both on a small sample before you commit to a 300 GB run.
Rsync is the right default for most transfers above 10 GB, for any link you do not fully trust, and any time you expect to sync the same directory more than once.
Also Read: Cloud GPU for AI Video Generation in 2026: VRAM Requirements Your Desktop Can’t Meet
Method 3: parallel transfers for maximum speed
A single stream can only go so fast. A parallel file transfer opens several connections at once, and on a fat link the difference is large: where one rsync stream might hold 50 to 60 MB/s, four in parallel can push 200 MB/s or more. For a fast file transfer gpu server teams can count on under deadline, this is usually the biggest single win.
GNU Parallel is the simplest way to spread a directory across several rsync jobs:
| # macOS brew install parallel# Linux sudo apt-get install parallel |
| find /path/to/model/ -type f | parallel -j 4 rsync -avz {} user@gpu-server.com:/models/{/} |
That runs four rsync processes at once, each handling different files. The same idea works with scp if you prefer it:
| ls /path/to/model_files/ | parallel -j 4 scp {} user@gpu-server.com:/models/{} |
For pulling data down rather than pushing it up, aria2 is a strong option because it splits a single download across connections:
| # macOS brew install aria2# Linux sudo apt-get install aria2 |
| aria2c -x 4 sftp://user@gpu-server.com/models/model.pth |
-x 4 opens four connections. Note the direction: aria2 is built for downloads, so it fits the remote-to-local case far better than local-to-remote uploads.
You can also tune a single rsync stream for a high-latency link:
| rsync -avz -e “ssh -o TCPKeepAlive=yes -o ConnectTimeout=5” /path/to/model.pth user@gpu-server.com:/models/model.pth |
Here is roughly how the methods stack up on a 100 GB model. Treat these as ballpark figures; your real numbers depend on the link and the server.
| Method | Typical speed | Time for 100 GB |
| scp | ~50 MB/s | ~33 minutes |
| rsync | ~60 MB/s | ~28 minutes |
| Parallel rsync (4 streams) | ~200 MB/s | ~8 minutes |
| Direct S3, same region | 400+ MB/s | ~4 minutes |
That table is also the honest argument for parallelism: to transfer 100gb model file payloads in single-digit minutes rather than half an hour, you need either several streams or a cloud-native path.
One warning. Parallel transfers eat network capacity and CPU on both ends. If your connection or the server is already busy, four streams can make everything slower, not faster. Start at two, watch the numbers, and raise the count only if throughput actually climbs. Reach for this when the file is very large, the link is 1 Gbps or better, and the clock matters.
Also Read: Cloud GPU for Running LLMs in 2026: When Your Local GPU Isn’t Enough
Method 4: a direct pull from S3 to the GPU server
If the model already lives in cloud storage, or you can put it there, the fastest path skips your home internet entirely. Moving data from s3 to gpu server inside the same cloud region runs over the provider’s internal network, where 400 to 500 MB/s is normal and resumption is handled for you.
You need three things: the model in an S3 bucket, credentials on the server that can read it, and the AWS CLI installed there.
Install the CLI on the server:
| curl “https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip” -o “awscliv2.zip” unzip awscliv2.zipsudo ./aws/install |
Add credentials:
| aws configure# Access key, secret key, and the region your bucket lives in, for example us-east-1 |
Pull a single file:
| aws s3 cp s3://your-bucket/model.pth /models/model.pth |
The CLI switches to multipart transfers automatically once a file crosses its threshold, which by default is 8 MB, not the hundreds of megabytes people often assume. That is why large files come down in parallel chunks without any extra flags. To add server-side encryption:
| aws s3 cp s3://your-bucket/large-model.pth /models/ –sse AES256 |
For a whole folder, sync keeps the two sides matched:
| aws s3 sync s3://your-bucket/models/ /models/ |
Add –delete only if you want files removed locally when they disappear from the bucket. Watch progress from a second shell:
| watch -n 5 ‘du -sh /models/’ |
Cost is worth a word, because the usual advice gets it wrong. Pulling from an S3 bucket to a server in the same region costs nothing for the transfer itself, which is the real reason this method is both fast and cheap. Cross-region transfers run around $0.02 per GB, and pulling out to the public internet is closer to $0.09 per GB after the first 100 GB each month. So keep the bucket and the GPU server in the same region whenever you can.
Use S3 when the model is already there, when your server sits in the same cloud, when speed is the priority, or when you need to fan the same model out to several servers at once. The catch is simple: if the model is only on your laptop, you still have to get it into S3 first, and that upload uses your home connection like any other.
Also Read: Cloud GPU in USA 2026: Latency, Data Residency & Best Options
Method 5: SFTP with resumption, the GUI friendly option
Not everyone wants to live in a terminal. SFTP runs file transfers over the same SSH connection, works in graphical clients, and supports resuming a stopped transfer. For anyone who would rather drag a file than type a command, it handles sftp large files jobs without much fuss.
FileZilla is the common choice, free and available on every platform. Point it at the server through File, then Site Manager:
- Protocol: SFTP
- Host: your-gpu-server.com
- User: your username
- Logon type: key file or password
- Connect, then drag files across
If a transfer is interrupted, FileZilla offers to resume it rather than start over.
You can also drive SFTP from the command line:
| sftp user@gpu-server.comget /models/model.pth /local/path/model.pth |
Inside the SFTP shell, use reget instead of get to resume a partial download. For a set of files, script it:
| cat > sftp_transfer.txt << ‘EOF’put /local/path/model.pth /models/model.pthput /local/path/config.json /models/config.jsonquitEOF sftp -b sftp_transfer.txt user@gpu-server.com |
SFTP sits between scp and rsync: friendlier than rsync, more capable than scp, and a good fit when you have a handful of files to place by hand and want to watch it happen. For unattended, very large, or repeated transfers, rsync still wins.
Also Read: Edge GPU vs Cloud GPU in 2026: Which One Should You Actually Use?
Model transfer optimization tips
Real model transfer optimization is less about one clever trick and more about stacking a few habits that each remove a bottleneck.
Shrink the model before it moves. Quantizing weights from 32-bit to 8-bit can cut a PyTorch model to a third of its size with little accuracy loss, and a smaller file is a shorter transfer:
| import torch model = torch.load(‘model.pth’) quantized = torch.quantization.quantize_dynamic( model, {torch.nn.Linear}, dtype=torch.qint8 ) torch.save(quantized, ‘model_compressed.pth’) |
Send the compressed version, then load it on the server.
Reuse one SSH connection instead of opening a new one per file:
| ssh -M -S ~/.ssh/control-%r@%h:%p -N user@gpu-server.com &rsync -avz -e “ssh -S ~/.ssh/control-%r@%h:%p” /path/to/model.pth user@gpu-server.com:/models/ |
On a directory of many small shards, the saved handshakes add up.
Split a very large file so you can send the pieces at once:
| split -b 50G model.pth model_part_for part in model_part_*; do rsync -avz $part user@gpu-server.com:/models/ &donewait |
Then rebuild it on the server:
| cat model_part_* > model.pth |
Always verify what landed. Hash the file before and after:
| # Localmd5sum model.pth > model.md5 scp model.md5user@gpu-server.com:/models/# On the servercd /models && md5sum -c model.md5 |
A result of model.pth: OK means the copy is byte-for-byte intact. Anything else means transfer it again.
Two more habits. Schedule big transfers for off-peak hours, since a congested daytime link can run several times slower than the same link at 2 a.m. And keep an eye on a long job while it runs:
| watch -n 5 ‘ls -lh /models/model.pth’iftop -i eth0 |
For anything automated, wrap the transfer in a retry loop so a brief network hiccup does not sink an overnight job:
| for i in 1 2 3; do rsync -avz –partial /path/to/model.pth user@gpu-server.com:/models/ && break sleep 60done |
None of these is dramatic on its own. Together they routinely turn an all-day upload into something you can finish over a coffee.
Also Read: Cloud GPU Security & Compliance: What You Must Know in 2026
Troubleshooting common transfer problems
Most transfer failures come down to a handful of errors. Here are the ones you will actually hit.
Connection timed out usually means the server is unreachable, a firewall is blocking the port, or the host is down. Check the basics first:
| ping gpu-server.com nc -zv gpu-server.com 22 # If SSH runs on a non-standard port ssh -p 2222 user@gpu-server.com |
Permission denied (publickey,password) points to the wrong username, the wrong key, or an expired credential:
| ssh -v user@gpu-server.com # read the debug output ssh -i ~/.ssh/my_key user@gpu-server.com |
No space left on device means the server disk filled mid-transfer. Check it, clear room, then resume:
| ssh user@gpu-server.com “df -h /” ssh user@gpu-server.com “rm -rf /tmp/*” rsync -avz –partial /path/to/model.pth user@gpu-server.com:/models/ |
Because you used –partial, the resume picks up rather than restarting.
rsync: connection unexpectedly closed is almost always an unstable link or an SSH session the server killed. Keep the connection alive:
| rsync -avz -e “ssh -o TCPKeepAlive=yes -o ServerAliveInterval=60” /path/to/model.pth user@gpu-server.com:/models/ |
A corrupted file that will not load is the nastiest one, because the transfer looked fine. This is what the hash check catches:
| md5sum model.pth > model.md5 scp model.md5 user@gpu-server.com:/models/ ssh user@gpu-server.com “cd /models && md5sum -c model.md5” # On mismatch, delete and resend ssh user@gpu-server.com “rm /models/model.pth” rsync -avz –partial /path/to/model.pth user@gpu-server.com:/models/ |
Painfully slow speed, say 5 to 10 MB/s when you expected far more, is usually congestion, compression overhead on already-compressed data, or a CPU bottleneck. Drop -z for binary files and spread the load:
| rsync -av /path/to/model.pth user@gpu-server.com:/models/ # no -z parallel -j 4 rsync -av {} user@gpu-server.com:/models/{/} ::: /path/to/model/*iftop # see the real usage |
Most of it traces back to three roots: an unstable network, which –partial handles; a full disk, which you check before starting; and single-stream slowness, which parallel transfers fix.
Also Read: Cloud GPU vs Owning GPUs 2026: Which Has Lower Cost?
Which method should you use?
Here is the whole thing on one screen.
| Method | File size | Typical speed | Resumes? | Ease | Best for |
| scp | Under 10 GB | ~50 MB/s | No | Easy | Quick one-offs |
| rsync | 10 to 100 GB | ~60 MB/s | Yes | Moderate | Most transfers |
| Parallel rsync | Over 100 GB | 200+ MB/s | Yes | Harder | Large, time-critical jobs |
| S3, same region | Any | 500+ MB/s | Automatic | Moderate | Cloud-native, many servers |
| SFTP | Any | ~60 MB/s | Yes | Easy | GUI preference |
The decision is quicker than the table makes it look. Is the model already in S3, with your server in the same region? Use the S3 pull; nothing else comes close. Not in S3, and larger than 100 GB? Parallel rsync. Between 10 and 100 GB? Plain rsync with –partial. Under 10 GB and a one-time job? scp is fine. Prefer a window over a prompt? SFTP.
On a 100 GB model, the rough finishing times line up like this: scp around 33 minutes, rsync around 28, parallel rsync near 8, and a same-region S3 pull close to 4. Real speeds move with your connection and the server’s load, so read these as the shape of the difference, not a guarantee. Most teams settle on rsync as the everyday default, keep S3 for anything already in the cloud, and pull out parallel transfers when a deadline makes the extra setup worth it.
A production-ready transfer script
For anything you run more than once, wrap the whole process, size check, hash, transfer, retry, and verify, into a single script:
| #!/bin/bash # transfer_model.sh – reliable model transfer with verification set -e SOURCE_PATH=$1 DEST_SERVER=$2 DEST_PATH=$3 MAX_RETRIES=3 RETRY_DELAY=60 if [ $# -ne 3 ]; then echo “Usage: ./transfer_model.sh <source> <server> <dest_path>” exit 1 fi echo “[INFO] Preparing transfer…” SOURCE_SIZE=$(du -sh “$SOURCE_PATH” | cut -f1) SOURCE_HASH=$(md5sum “$SOURCE_PATH” | awk ‘{print $1}’) echo “[INFO] Source size: $SOURCE_SIZE” echo “[INFO] Source hash: $SOURCE_HASH” ssh $DEST_SERVER “mkdir -p $DEST_PATH” for attempt in $(seq 1 $MAX_RETRIES); do echo “[ATTEMPT $attempt/$MAX_RETRIES] Starting transfer…” if rsync -avz –partial –human-readable \ -e “ssh -o TCPKeepAlive=yes -o ServerAliveInterval=60” \ “$SOURCE_PATH” $DEST_SERVER:”$DEST_PATH/”; then echo “[SUCCESS] Transfer completed” break else if [ $attempt -lt $MAX_RETRIES ]; then echo “[RETRY] Waiting ${RETRY_DELAY}s before retry…” sleep $RETRY_DELAY else echo “[FAILED] Transfer failed after $MAX_RETRIES attempts” exit 1 fi fi done echo “[INFO] Verifying integrity…” DEST_HASH=$(ssh $DEST_SERVER “md5sum $DEST_PATH/$(basename $SOURCE_PATH) | awk ‘{print \$1}'”) if [ “$SOURCE_HASH” = “$DEST_HASH” ]; then echo “[SUCCESS] Hash verified, transfer complete and intact” else echo “[ERROR] Hash mismatch, transfer may be corrupted” exit 1 fi |
Run it:
| chmod +x transfer_model.sh ./transfer_model.sh /local/model.pth user@gpu-server.com /models/ |
The script hashes the file, transfers with resumption, retries up to three times with a pause between attempts, and confirms the copy matches before it calls the job done. Point it at a model and walk away; if it exits cleanly, the file is on the server and verified.
Also Read: Cloud GPU Availability in 2026: Which GPUs Are Easy to Get Right Now?
Transferring models to Hostrunway GPU servers
Everything above is faster when the infrastructure on the other end is built for it.
Model transfers to Hostrunway GPU servers move quickly because the platform keeps high-speed, low-latency links to the major cloud providers, including AWS S3 and Google Cloud Storage. A 100 GB model coming from S3 lands in minutes rather than hours.
The S3 path in particular needs no setup. Hostrunway GPU servers come with pre-configured AWS IAM roles for S3 access, so there are no credentials to wire up. You run aws s3 cp and the transfer moves at 500 MB/s speeds, roughly ten times faster than pushing the same file through a home connection.
Location helps too. With 160+ data center locations, if your model is cached or replicated across regions, you can pull it from the one closest to your server and cut out the extra network hops.
Spending hours watching an upload bar crawl is a tax on every training cycle. GPU servers with direct S3 integration remove that wait and turn transfer time from hours into minutes.
Whether you land on rsync, parallel uploads, or a direct S3 pull, the infrastructure underneath is what decides how fast a large model actually arrives.
Frequently asked questions
What is the fastest way to transfer a 500 GB model?
The direct S3 pull, run inside the same cloud region as your server. It uses the provider’s internal network instead of your home link, so 400 to 500 MB/s is realistic, and a 500 GB model can land in under half an hour. If the model is not in cloud storage, the next best option is parallel rsync with four to eight streams, plus –partial so a drop never costs you the whole job.
Can I transfer multiple models simultaneously to avoid transfer queueing?
Yes, and it often helps. Running two or three rsync jobs at once can fill capacity that a single stream leaves idle. The limit is your total upload rate and the server’s CPU, not the number of files. If combined throughput stops climbing as you add jobs, you have hit the ceiling, and more parallelism will only add overhead. Start with two, measure, and scale from there.
Should I compress models during transfer to save bandwidth?
For model weights, usually not. PyTorch and most checkpoint formats are already compressed, so rsync’s -z or scp’s -C spends CPU for almost no size reduction, and on a fast link that overhead can slow you down. Compression pays off for text-heavy or uncompressed formats. A better move is to shrink the model itself through quantization before transfer, which reduces the actual bytes rather than squeezing an already-packed file.
How do I know if my transfer was successful after it completes?
Check the file, not the exit message. Generate a checksum on both ends and compare them: md5sum model.pth locally, the same command on the server, and confirm the two strings match. A model.pth: OK from md5sum -c means the copy is byte-for-byte identical. Matching file sizes alone are not enough, because a truncated or corrupted file can still report a plausible size. The hash is the only real proof.
Can I pause and resume an rsync transfer if I need to disconnect?
Yes, as long as you use –partial. That flag tells rsync to keep the portion it has already sent, so when you reconnect and run the same command, it resumes from where it stopped instead of starting over. Without –partial, an interrupted transfer discards the incomplete file. For long jobs, add –append-verify if you want rsync to checksum the existing data before continuing, which guards against a partial file left in a bad state.
What if my SSH key gets compromised during a transfer, is the file encrypted?
The transfer itself is encrypted in transit, whether you use scp, rsync over SSH, or SFTP, so someone watching the network cannot read the file as it moves. A compromised private key is a different problem: it is about access, not interception. If a key leaks, rotate it right away with ssh-keygen, remove the old public key from the server’s authorized_keys, and check the server’s auth logs for any session you did not start.
How do I transfer models securely so no one else on the network can see them?
All the SSH-based methods here already encrypt the connection, so other users on the same network cannot read your data in transit. On the server side, lock down the destination: set tight permissions with chmod 700, store models under a path only your user can reach, and prefer key-based login over passwords. If the model is sensitive at rest, encrypt the file before you send it, and for S3 use bucket policies plus server-side encryption.
Can I transfer from one GPU server to another without going through my local machine?
Yes. rsync can run between two remote hosts, and scp’s -3 routes a remote-to-remote copy through your machine as a relay without writing the file to your disk. The faster route, if both servers are in the same cloud, is to push the model to S3 once and pull it onto each server from there, which keeps every hop on the provider’s internal network instead of your connection.
What if the model file is split across multiple files, such as shards?
Treat the shard directory as the unit, not each file. rsync copies a whole folder in one command and, with –partial, resumes cleanly if it drops partway through: rsync -avz –partial /path/to/shards/ user@server:/models/shards/. For speed, feed the file list to GNU Parallel so several shards move at once. Whatever you do, verify the complete set with a checksum afterward, because a model missing even one shard will fail to load.
Is it faster to upload to S3 first, then transfer from S3 to the GPU server, or transfer directly from my machine?
It depends on where your server lives. If the server is in the same cloud region as the bucket, uploading to S3 first and pulling from there is faster overall, because the second hop runs on the internal network at several hundred MB/s. If the server is outside that cloud, the S3 detour adds an upload you would otherwise skip, so a direct parallel rsync is usually quicker. The same cloud favors S3; everything else favors direct.
How do I monitor transfer progress in real-time without SSH into the server?
A few options. rsync and scp print a live progress bar in the terminal that launched them, so you do not need a second session for the basics. For a server-side view without a full login, a short watch command over SSH, such as watch -n 5 ‘du -sh /models/’, shows the folder growing. If you want a dashboard, tools like Netdata or a simple cron job that writes sizes to a log let you check progress from a browser.
