Я не знаком с наборами инструментов Matlab GPU, но подозреваю, что вторая передача (которая возвращает данные из GPU) начинается до того, как закончится первая.
% Time sending to GPU
sendFcn = @() gpuArray(hostData);
sendTimes(ii) = gputimeit(sendFcn);
%
%No synchronization here
%
% Time gathering back from GPU
gatherFcn = @() gather(gpuData);
gatherTimes(ii) = gputimeit(gatherFcn);
Аналогичный вопрос для программы на C был размещен здесь:
копирование с графического процессора на процессор выполняется медленнее, чем копирование процессора на графический процессор
В этом случае нет явной синхронизации после запуска потока в графическом процессоре и получения данных результатов из графического процессора.
Поэтому функция, которая возвращает данные, в C cudaMemcpy (), должна ждать, пока графический процессор завершит предыдущий запущенный поток, прежде чем передавать данные, увеличивая тем самым время, измеренное для передачи данных.
С помощью Cuda C API можно заставить процессор ждать, пока графический процессор завершит работу ранее запущенных потоков, с помощью:
cudaDeviceSynchronize ();
И только потом начинайте измерять время для передачи данных обратно.
Может быть, в Matlab есть также какой-то примитив синхронизации.
Также в том же ответе рекомендуется измерять время с помощью (Cuda) Events.
В этом POST по оптимизации передачи данных, также в C извините, события используются для измерения времени передачи данных:
https://devblogs.nvidia.com/how-optimize-data-transfers-cuda-cc/
Время передачи данных одинаково в обоих направлениях.