ArrayFlatten
works faster if you can reshape the entire data at once:
In[39]:= testData = RandomInteger[{0, 100}, {176851, 4}];
In[45]:= AbsoluteTiming[
res = ArrayReshape[testData, {First@Dimensions@testData, 2, 2}]][[1]]
Out[45]= 0.004762
In[46]:= AbsoluteTiming[
respart = {#[[1 ;; 2]], #[[3 ;; 4]]} & /@ testData][[1]]
Out[46]= 0.094411
In[47]:= res == respart
Out[47]= True
If you must perform the reshape inside an inner loop, then the overhead of arguments checking, etc. has to become a burden---as you found out.