极智AI | 谈谈GPU并行推理的几个方式

本文涉及的产品
视觉智能开放平台,视频资源包5000点
视觉智能开放平台,分割抠图1万点
视觉智能开放平台,图像资源包5000点
简介: 大家好,我是极智视界,本文主要聊一下 GPU 并行推理的几个方式。

大家好,我是极智视界。本文主要聊一下 GPU 并行推理的几个方式。

CUDA流 表示一个 GPU 操作队列,该队列中的操作将以添加到流中的先后顺序而依次执行。可以将一个流看做是GPU 上的一个任务,不同任务可以并行执行。使用 CUDA流,首先要选择一个支持设备重叠(Device Overlap)功能的设备,支持设备重叠功能的 GPU 能够在执行一个 CUDA 核函数的同时,还能在主机和设备之间执行复制数据操作。

支持重叠功能的设备的这一特性很重要,可以在一定程度上提升 GPU 程序的执行效率。一般情况下,CPU 内存远大于 GPU 内存,对于数据量比较大的情况,不可能把 CPU 缓冲区中的数据一次性传输给 GPU,需要分块传输,如果能够在分块传输的同时,GPU 也在执行核函数运算,这样就形成了异步操作,能够提高极大提升运算性能。

下面实际介绍几种 GPU 并行的方式。


1 Cuda 核函数并行

void privateBlobFromImagesGpu(const float* imageDatas, int batchCount, int width, int height, const float* mean, const float* std, float* blob, cudaStream_t stream)
{
  const dim3 block(3, width);
  const dim3 grid(height, batchCount);
  meanAndStdAndSplit <<<grid, block, 0, stream >>> (blob, imageDatas, mean, std);
}
global static void meanAndStdAndSplit(float* blob, const float* imageDatas, const float* mean, const float* std)
{
  const int c = threadIdx.x;
  const int x = threadIdx.y;
  const int y = blockIdx.x;
  const int idx = blockIdx.y; 
  const unsigned int blobIdx = idx * blockDim.x * blockDim.y * gridDim.x + c * blockDim.y * gridDim.x + y * blockDim.y + x;
  const unsigned int imagesIdx = idx * blockDim.x * blockDim.y * gridDim.x + y * blockDim.x * blockDim.y + x * blockDim.x + c;
  blob[blobIdx] = (imageDatas[imagesIdx] - mean[c]) / std[c];
}
for (int i = 0; i < thNB; i++)
{
  privateBlobFromImagesGpu((float*)m_converArray, imgdata.size.size(), m_inputW, m_inputH, m_mean_GPU, m_std_GPU,
  (float*)m_Bindings.at(m_InputIndex), cudaStream[i]);
}
for (int i = 0; i < thNB; i++)
{
  cudaStreamSynchronize(cudaStream);
}


2 调用英伟达 API 库并行

for (int i = 0; i < imgdata.size.size(); i++)
{
  cv::cuda::GpuMat gpuRgbSrcImg(cv::Size(imgdata.size[i].w, imgdata.size[i].h), CV_8UC3, (cv::uint8_t*)imgdata.data + i * imgdata.size[i].w * imgdata.size[i].h);
  cv::cuda::GpuMat gpuRgbDstImg(cv::Size(m_inputW, m_inputH), CV_8UC3, (cv::uint8_t*)m_resizeArray + i * m_inputC * m_inputH * m_inputW);
  cv::cuda::resize(gpuRgbSrcImg, gpuRgbDstImg, cv::Size(m_inputW, m_inputH), 0.0, 0.0, cv::INTER_LINEAR);
  cv::cuda::GpuMat dst_conver(outputSize, CV_32FC3, (float*)m_converArray + i * m_inputC * m_inputH * m_inputW);
  gpuRgbDstImg.convertTo(dst_conver, CV_32F, 1.0 / 255, 0);
}
stream.waitForCompletion();


3 TRT 并行

int testStream()
{
  int outNB = 0;
  std::string model_path = "./data/";
  int batchsize = 4;
  int streamNB = 2;
  DoInference *doInfer_stream1 = new DoInference();
  std::vector<int> outputSize;
  bool isInit1 = doInfer_stream1->InitModle(model_path, OD, TensorRT, outputSize, streamNB, batchsize);
  std::vector<float*> inputData;
  std::vector<cudaStream_t> cudaStream;
  std::vector<vector<void*>>imgdata_stream;
  inputData.resize(streamNB);
  cudaStream.resize(streamNB);
  int* size = new int[4];
  size[0] = 512 * 512 * 3;
  size[1] = 135168;
  size[2] = 33792;
  size[3] = 8848;
  imgdata_stream.resize(streamNB);
  for (int i = 0; i < streamNB; i++)
  {
    cudaStreamCreate(&cudaStream.at(i));
    cudaStreamCreateWithFlags(&cudaStream.at(i), cudaStreamNonBlocking);
    cudaMallocHost(&inputData.at(i), batchsize * size[0] * sizeof(float));
    imgdata_stream.at(i).resize(4);
    for (int j = 0; j < 4; j++)
    {
      cudaMalloc(&imgdata_stream.at(i).at(j), batchsize * size[j] * sizeof(float));
    }
    for (int z = 0; z < size[0]; z++)
    {
      inputData.at(i)[z] = z;
    } 
  }
  for (int count = 0; count < 5; count++)
  {
    for (int i = 0; i < streamNB; i++)
    {
      cudaMemcpyAsync(imgdata_stream.at(i).at(0), inputData.at(i), batchsize * size[0] * sizeof(float), cudaMemcpyHostToDevice, cudaStream.at(i));
      doInfer_stream1->DoinferTestStream(imgdata_stream.at(i), batchsize, i, cudaStream.at(i));
    }
  }
  for (int i = 0; i < streamNB; i++)
  {
    cudaStreamSynchronize(cudaStream.at(i));
  }
  //cudaStreamSynchronize(cudaStream1);
  //cudaStreamSynchronize(cudaStream2); 
  return 0;
}


好了,以上聊了下 GPU 并行推理的几个方式,希望我的分享能对你的学习有一点帮助。


logo_show.gif

相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
打赏
0
0
0
0
7
分享
相关文章
MiniMind:2小时训练出你的专属AI!开源轻量级语言模型,个人GPU轻松搞定
MiniMind 是一个开源的超小型语言模型项目,帮助开发者以极低成本从零开始训练自己的语言模型,最小版本仅需25.8M参数,适合在普通个人GPU上快速训练。
88 10
MiniMind:2小时训练出你的专属AI!开源轻量级语言模型,个人GPU轻松搞定
PRefLexOR:MIT自进化AI框架上线!动态知识图谱+跨域推理,重塑自主思考
PRefLexOR 是 MIT 团队推出的新型自学习 AI 框架,结合偏好优化和强化学习,通过递归推理和多步反思,动态生成知识图谱,支持跨领域推理和自主学习。
35 2
PRefLexOR:MIT自进化AI框架上线!动态知识图谱+跨域推理,重塑自主思考
AI 场景下,函数计算 GPU 实例模型存储最佳实践
AI 场景下,函数计算 GPU 实例模型存储最佳实践
【活动报名】​AI应用启航workshop:瓴羊+通义助力企业迈入AI驱动的数智营销时代
【活动报名】​AI应用启航workshop:瓴羊+通义助力企业迈入AI驱动的数智营销时代
从零开始即刻拥有 DeepSeek-R1 满血版并使用 Dify 部署 AI 应用
本文介绍了如何使用阿里云提供的DeepSeek-R1大模型解决方案,通过Chatbox和Dify平台调用百炼API,实现稳定且高效的模型应用。首先,文章详细描述了如何通过Chatbox配置API并开始对话,适合普通用户快速上手。接着,深入探讨了使用Dify部署AI应用的过程,包括选购云服务器、安装Dify、配置对接DeepSeek-R1模型及创建工作流,展示了更复杂场景下的应用潜力。最后,对比了Chatbox与Dify的输出效果,证明Dify能提供更详尽、精准的回复。总结指出,阿里云的解决方案不仅操作简便,还为专业用户提供了强大的功能支持,极大提升了用户体验和应用效率。
420 18
从零开始即刻拥有 DeepSeek-R1 满血版并使用 Dify 部署 AI 应用
容器化浪潮下的AI赋能:智能化运维与创新应用
近年来,容器技术以其轻量、高效、可移植的特性成为云原生时代的基石,推动应用开发和部署方式革新。随着容器化应用规模扩大,传统运维手段逐渐力不从心。AI技术的引入为容器化生态带来新活力,实现智能监控、自动化故障诊断与修复及智能资源调度,提升运维效率和可靠性。同时,AI驱动容器化创新应用,如模型训练、边缘计算和Serverless AI服务,带来更多可能性。未来,AI与容器技术的融合将更加紧密,推动更智能、高效的运维平台和丰富的创新应用场景,助力数字化转型。
Spring AI与DeepSeek实战一:快速打造智能对话应用
在 AI 技术蓬勃发展的今天,国产大模型DeepSeek凭借其低成本高性能的特点,成为企业智能化转型的热门选择。而Spring AI作为 Java 生态的 AI 集成框架,通过统一API、简化配置等特性,让开发者无需深入底层即可快速调用各类 AI 服务。本文将手把手教你通过spring-ai集成DeepSeek接口实现普通对话与流式对话功能,助力你的Java应用轻松接入 AI 能力!虽然通过Spring AI能够快速完成DeepSeek大模型与。
141 11
Serverless + AI 让应用开发更简单,加速应用智能化
Serverless + AI 让应用开发更简单,加速应用智能化
Java 也能快速搭建 AI 应用?一文带你玩转 Spring AI 可观测性
Java 也能快速搭建 AI 应用?一文带你玩转 Spring AI 可观测性

热门文章

最新文章