显示硬件发展与视频开发系列(6)----显示标注与视频处理单元(3):APU

       APU是“Accelerated Processing Units”的简称,中文名字叫加速处理器,是AMD融聚未来理念的产品,它第一次将处理器和独显核心做在一个晶片上。

       CPU与APU协同计算、彼此加速,具有高性能处理器和最新支持DX11独立显卡的处理性能,大幅提升电脑运行效率,实现了CPU与GPU真正的融合。APU是处理器未来发展的趋势。

7.3.1、AMD与APU

       从APU发展来看,AMD让CPU和GPU彻底融为一体,无论是AMD的Llano,还是Brazos,目标都是一致的。

       AMD认为,CPU和GPU的融合分为四步进行:

       第一步:物理整合(Physical Integration),将CPU和GPU集成在同一块硅芯片上,利用高带宽的内部总线通讯,集成高性能的内存控制器,借助开放的软件系统促成异构计算。

       第二步:平台优化(Optimized Platforms),CPU和GPU之间互连接口进一步增强,统一进行双向电源管理,GPU支持高级编程语言。

       第三步:架构整合(Architectural Integration),实现统一的CPU/GPU寻址空间、GPU使用可分页系统内存、GPU硬件可调度、CPU/GPU/APU内存协同一致。

       第四步:架构和系统整合(Architectural & OS Integration),主要特点包括GPU计算环境切换、GPU图形优先计算、独立显卡的PCI-E协同、任务并行运行实时整合等等。

       AMD Fusion系列APU将多核(x86)中央处理器、支持DX11标准的强大独立显卡性能以及高速总线融合在一块芯片上,拥有并行处理引擎和专门高清视频加速模块,实现数据在不同处理核心间的加速传递。

       基于AMD Fusion APU的台式机、笔记本和高清轻薄本已经销售多年。基于AMD Fusion APU的平板电脑和嵌入式电脑有很多优点。高清视频播放效果流畅,满足多种应用的突破性的计算能力,全面支持DX以及强大的电池续航能力。

       AMD通过和宏碁、华硕、戴尔、富士通、惠普、联想、微星、三星、索尼、东芝等领先PC厂商合作,在电脑上推出基于AMD Fusion APU的新品。

AMD公司高级副总裁Rick Bergman表示:“简而言之,我认为AMD Fusion加速处理器是自从x86架构问世之后40余年来处理器领域最伟大的进步。通过这一跨越,我们让顾客能够随时随地体验高清视频、享受       超级个人计算体验,并且让笔记本电脑具备全天的电池续航能力。这是一个全新的产品系列,全新的视角,给消费者带来全新的精彩应用体验。”

7.3.2、VISION引擎

       随着硬件技术的进步,高清视频的时代到来了。从YouTube视频网站到DirectX12电脑游戏再到蓝光碟片,得到广泛应用。AMD VISION引擎横空出世,一系列与高清视频相关的独特性能将使基于AMD APU的个人电脑为用户带来更加生动与逼真的高清视频体验。

       VISION引擎汇集了下列功能:

  1. 支持DirectX11标准
  2. 强大的并行处理能力加速应用性能提升
  3. AMD Radeon™ HD 6800系列显卡整合UVD3视频加速模块
  4. 独特的图形驱动程序,每月更新,不断提高视频性能。

       带有VISION引擎标识的电脑代表着更强大的性能。更流畅的上网体验;华丽、流畅、安静的高清视频播放;使标清视频播放出高清效果;将2D内容转换成更立体的3D格式;轻松高清应用;为用户带来3D游戏体验。

       运算体验与软件密不可分,开发者受到CPU和GPU处理信息时各自为战进行独立计算的制约。今天,AMD Fusion APU消除了这一障碍,开发者可以利用GPU的并行处理能力。

       AMD Fusion技术全天电池续航能力,续航时间长达10小时以上。单芯片设计所带来的节电效果超过我们的预料。

7.3.3、APU新品

       锐龙7 5700G处理器采用Cezanne(塞尚)核心,与AMD路线图中一致。其最高频率大约为4.75GHz,为8核16线程,三级缓存为16MB,只有“标准版”的一半,CPU测试成绩则绝对是锐龙5000级别的,轻松压制十代酷睿和自家的锐龙3000。

7.3.4、APU编程

       APU没有设计独立的开发环境,APU目前支持OpenCL与OpenGL、DirectX等。在并行编程领域,主要支持的是OpenCL。

      下面是OpenCL示例代码:

#include <iostream>
#include <fstream>
#include <sstream>
#include <CL/cl.h>

const int ARRAY_SIZE = 1000;

//一、 选择OpenCL平台并创建一个上下文
cl_context CreateContext()
{
       cl_int errNum;
       cl_uint numPlatforms;
       cl_platform_id firstPlatformId;
       cl_context context = NULL;

       //选择可用的平台中的第一个
       errNum = clGetPlatformIDs(1, &firstPlatformId, &numPlatforms);
       if (errNum != CL_SUCCESS || numPlatforms <= 0)
       {
              std::cerr << "Failed to find any OpenCL platforms." << std::endl;
              return NULL;
       }

       //创建一个OpenCL上下文环境
       cl_context_properties contextProperties[] =
       {
              CL_CONTEXT_PLATFORM,
              (cl_context_properties)firstPlatformId,
              0
       };

       context = clCreateContextFromType(contextProperties, CL_DEVICE_TYPE_GPU,
              NULL, NULL, &errNum);

       return context;
}

//二、 创建设备并创建命令队列
cl_command_queue CreateCommandQueue(cl_context context, cl_device_id *device)
{
       cl_int errNum;
       cl_device_id *devices;
       cl_command_queue commandQueue = NULL;
       size_t deviceBufferSize = -1;
       // 获取设备缓冲区大小
       errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, 0, NULL, &deviceBufferSize);
       if (deviceBufferSize <= 0)
       {
              std::cerr << "No devices available.";
              return NULL;
       }

       // 为设备分配缓存空间
       devices = new cl_device_id[deviceBufferSize / sizeof(cl_device_id)];
       errNum = clGetContextInfo(context, CL_CONTEXT_DEVICES, deviceBufferSize, devices, NULL);

       //选取可用设备中的第一个
       commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL);

       *device = devices[0];
       delete[] devices;
       return commandQueue;
}

// 三、创建和构建程序对象
cl_program CreateProgram(cl_context context, cl_device_id device, const char* fileName)
{
       cl_int errNum;
       cl_program program;

       std::ifstream kernelFile(fileName, std::ios::in);
       if (!kernelFile.is_open())
       {
              std::cerr << "Failed to open file for reading: " << fileName << std::endl;
              return NULL;
       }

       std::ostringstream oss;
       oss << kernelFile.rdbuf();
       std::string srcStdStr = oss.str();
       const char *srcStr = srcStdStr.c_str();
       program = clCreateProgramWithSource(context, 1,
              (const char**)&srcStr,
              NULL, NULL);

       errNum = clBuildProgram(program, 0, NULL, NULL, NULL, NULL);
       return program;
}

//创建和构建程序对象
bool CreateMemObjects(cl_context context, cl_mem memObjects[3],
       float *a, float *b)
{
       memObjects[0] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
              sizeof(float) * ARRAY_SIZE, a, NULL);
       memObjects[1] = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR,
              sizeof(float) * ARRAY_SIZE, b, NULL);
       memObjects[2] = clCreateBuffer(context, CL_MEM_READ_WRITE,
              sizeof(float) * ARRAY_SIZE, NULL, NULL);
       return true;
}

// 释放OpenCL资源
void Cleanup(cl_context context, cl_command_queue commandQueue,
       cl_program program, cl_kernel kernel, cl_mem memObjects[3])
{
       for (int i = 0; i < 3; i++)
       {
              if (memObjects[i] != 0)
                     clReleaseMemObject(memObjects[i]);
       }
       if (commandQueue != 0)
              clReleaseCommandQueue(commandQueue);

       if (kernel != 0)
              clReleaseKernel(kernel);
       if (program != 0)
              clReleaseProgram(program);
       if (context != 0)
              clReleaseContext(context);
}

int main(int argc, char** argv)
{
       cl_context context = 0;
       cl_command_queue commandQueue = 0;
       cl_program program = 0;
       cl_device_id device = 0;
       cl_kernel kernel = 0;
       cl_mem memObjects[3] = { 0, 0, 0 };
       cl_int errNum;

       // 一、选择OpenCL平台并创建一个上下文
       context = CreateContext();

       // 二、 创建设备并创建命令队列
       commandQueue = CreateCommandQueue(context, &device);

       //创建和构建程序对象
       program = CreateProgram(context, device, "HelloWorld.cl");

       // 四、 创建OpenCL内核并分配内存空间
       kernel = clCreateKernel(program, "hello_kernel", NULL);

       //创建要处理的数据
       float result[ARRAY_SIZE];
       float a[ARRAY_SIZE];
       float b[ARRAY_SIZE];
       for (int i = 0; i < ARRAY_SIZE; i++)
       {
              a[i] = (float)i;
              b[i] = (float)(ARRAY_SIZE - i);
       }

       //创建内存对象
       if (!CreateMemObjects(context, memObjects, a, b))
       {
              Cleanup(context, commandQueue, program, kernel, memObjects);
              return 1;
       }

       // 五、 设置内核数据并执行内核
       errNum = clSetKernelArg(kernel, 0, sizeof(cl_mem), &memObjects[0]);
       errNum |= clSetKernelArg(kernel, 1, sizeof(cl_mem), &memObjects[1]);
       errNum |= clSetKernelArg(kernel, 2, sizeof(cl_mem), &memObjects[2]);

       size_t globalWorkSize[1] = { ARRAY_SIZE };
       size_t localWorkSize[1] = { 1 };

       errNum = clEnqueueNDRangeKernel(commandQueue, kernel, 1, NULL,
              globalWorkSize, localWorkSize,
              0, NULL, NULL);

       // 六、 读取执行结果并释放OpenCL资源
       errNum = clEnqueueReadBuffer(commandQueue, memObjects[2], CL_TRUE,
              0, ARRAY_SIZE * sizeof(float), result,
              0, NULL, NULL);

       for (int i = 0; i < ARRAY_SIZE; i++)
       {
              std::cout << result[i] << " ";
       }

       std::cout << std::endl;
       std::cout << "Executed program succesfully." << std::endl;
       getchar();
       Cleanup(context, commandQueue, program, kernel, memObjects);

       return 0;
}

7.3.5、总结

       APU的成功,巩固了AMD的市场,和INTEL形成有力的竞争。推动处理器技术、架构技术、并行计算技术的发展。多年以来,INTEL吊打AMD,APU的出现,这一局面得到改变。

       并行计算领域,APU主要支持OpenCL技术,随着时间的推移,OpenCL技术将不断完善,驱动将不断更新。

       AMD有着光辉的过去,也应该有着辉煌的明天。为处理器的发展做出了卓越的贡献。图为台湾籍AMD总裁苏姿丰女士。英伟达的黄仁勋为苏姿丰的舅舅。在芯片领域,台籍华人有着卓越的贡献。

猜你喜欢

转载自blog.csdn.net/qq_33277028/article/details/114274663