This commonly happens on the GPU, but there are trade offs for both and it's up to you to decide which will work best for you.
Doing the manipulation on the GPU means you only need to send the mesh data once, then you can just send the matrix transforms to deform it. This is great because it greatly reduces the bandwith required between CPU->GPU. It also means you can upload just one copy of the mesh to the GPU and apply transforms for many different instances of the mesh. However, it's more difficult to have "mesh accurate" collisions. Since the transforms are done on the GPU, you don't have them available to test with on the CPU.
Doing the manipulation on the CPU means you have access to the transformed mesh. You can access everything you need to know about it. However, it means you need to upload that entire mesh to the GPU each frame. It also means you have to upload a transformed mesh for each instance of that mesh. In summary here's a no where near exhaustive list of pros and cons.
Pros for GPU
- Upload the mesh data once
- Transform it for multiple instances
- Only need to send the matrix transforms
- The GPU is very good at parallelizing these types of things
Cons for GPU
- Transformed meshes are not available for testing on CPU
Pros for CPU
- Transformed meshes are available for collision tests and anything else needed.
Cons for CPU
- Need to upload the entire transformed mesh each frame
- Need to upload an entire mesh for each instance of the mesh
There are ways to get around the cons for the GPU however.
- Don't have mesh accurate collisions. Use something "close enough" like a bounding box for the entire mesh or have bounding boxes for each bone of the mesh. The below is using on the GPU transforms for the mesh, and on the CPU transforms for axis aligned bounding boxes that represent the mesh. You could get even more accurate bounds by using non-AABBs.
- Transform a copy of the mesh on the CPU if and only if mesh accurate collisions are needed. After a bounding box collision has returned true, transform a mesh to match the transforms on the GPU, then check the collisions against that to get more accurate collision data.
All-in-all I assume you can see why it's more common to transform on the GPU