使用 accelerator 和 accelerator_view 对象
您可使用快捷键和 accelerator_view 类来指定设备或仿真器以运行 C++ AMP 代码。 系统可能有由内存量、共享内存支持、调试支持或双精度支持不同的多台计算机或模拟器。 C++ Accelerated Massive Parallelism (C++ AMP) 提供您能使用的 API 来检查可用的加速器,设置一个默认加速器,指定对parallel_for_each 的多个调用的多个加速器视图,并执行特殊调试任务。
使用默认快捷键
除非您编写代码选择特定快捷键,否则 C++ AMP 运行时会选择默认快捷键。 运行时选择如下所示的默认值快捷键:
如果应用程序正在运行调试模式而支持调试的加速器。
否则,则为 CPPAMP_DEFAULT_ACCELERATOR 环境变量指定的快捷键,如果已设置的话。
否则,则为非模拟的计算机。
否则,则为具有的最大数量可用内存的计算机。
否则,则为未附加到该显示屏的计算机。
此外,运行时为默认快捷键指定了 access_type_auto 的 access_type。 这意味着,如果默认快捷键受支持或如果其性能特征与已知的专用(非共享)内存一致,则其可使用共享内存。
您可通过构造默认快捷键并检查其属性来确定默认快捷键的属性。 以下代码示例输出路径、快捷键内存量、共享内存支持、双精度支持,以及默认快捷键的有限双精度支持。
void default_properties() {
accelerator default_acc;
std::wcout << default_acc.device_path << "\n";
std::wcout << default_acc.dedicated_memory << "\n";
std::wcout << (accs[i].supports_cpu_shared_memory ?
"CPU shared memory: true" : "CPU shared memory: false") << "\n";
std::wcout << (accs[i].supports_double_precision ?
"double precision: true" : "double precision: false") << "\n";
std::wcout << (accs[i].supports_limited_double_precision ?
"limited double precision: true" : "limited double precision: false") << "\n";
}
CPPAMP_DEFAULT_ACCELERATOR 环境变量
您可设置 CPPAMP_DEFAULT_ACCELERATOR 环境变量以指定默认快捷键的 accelerator::device_path。 路径取决于硬件。 以下代码使用 accelerator::get_all 函数检索可用快捷键的列表,随后显示每个快捷键的路径和特性。
void list_all_accelerators()
{
std::vector<accelerator> accs = accelerator::get_all();
for (int i = 0; i < accs.size(); i++) {
std::wcout << accs[i].device_path << "\n";
std::wcout << accs[i].dedicated_memory << "\n";
std::wcout << (accs[i].supports_cpu_shared_memory ?
"CPU shared memory: true" : "CPU shared memory: false") << "\n";
std::wcout << (accs[i].supports_double_precision ?
"double precision: true" : "double precision: false") << "\n";
std::wcout << (accs[i].supports_limited_double_precision ?
"limited double precision: true" : "limited double precision: false") << "\n";
}
}
选择一个快捷键
若要选择快捷键,请使用 accelerator::get_all 方法检索可用快捷键列表,然后根据其属性选择一个快捷键。 此示例演示了如何选择具有最多内存的加速器:
void pick_with_most_memory()
{
std::vector<accelerator> accs = accelerator::get_all();
accelerator acc_chosen = accs[0];
for (int i = 0; i < accs.size(); i++) {
if (accs[i].dedicated_memory > acc_chosen.dedicated_memory) {
acc_chosen = accs[i];
}
}
std::wcout << "The accelerator with the most memory is "
<< acc_chosen.device_path << "\n"
<< acc_chosen.dedicated_memory << ".\n";
}
备注
由 accelerator::get_all 返回的某个快捷键是 CPU 快捷键。您无法在 CPU 加速器 上执行代码。若要筛选 CPU 快捷键,请将由 accelerator::get_all 返回的快捷键的 device_path 属性值与 accelerator::cpu_accelerator 值进行比较。有关详情,请参阅本文的“特殊快捷键”章节。
共享内存
共享内存是可以同时由 CPU 和快捷键访问的内存。 使用共享内存消除或显著降低 CPU 和快捷键之间复制数据的开销。 虽然内存共享,但不能使用 CPU 和 加速器同时访问内存,如果同时访问则会导致未定义的行为。 如果快捷键支持共享内存,则快捷键属性 supports_cpu_shared_memory 返回 true,并且 default_cpu_access_type 属性获得分配在 accelerator 上的内存的默认 access_type — 例如与 accelerator 关联的 array 或在 accelerator 上访问的 array_view 对象。
C++ AMP 运行时自动为每个 accelerator 选择最佳默认 access_type,但在从 CPU 读取或写入或同时读写时,共享内存的性能特征(带宽和延迟)可能比不上专用(非共享)快捷键内存。 如果共享内存在执行从 CPU 中读取和写入时的表现与专用内存一样优异,运行时将默认为 access_type_read_write;否则,运行时将选择更保守的默认 access_type,并且如果不同的 access_type 有益于计算内核的内存访问模式,运行时将允许应用程序对其进行重写。
以下代码示例演示如何确定默认快捷键是否支持共享内存,然后重写默认访问类型,并根据它创建 accelerator_view。
#include <amp.h>
#include <iostream>
using namespace Concurrency;
int main()
{
accelerator acc = accelerator(accelerator::default_accelerator);
// Early out if the default accelerator doesn’t support shared memory.
if(!acc.supports_cpu_shared_memory)
{
std::cout << "The default accelerator does not support shared memory" << std::endl;
return 1;
}
// Override the default CPU access type.
acc.set_default_cpu_access_type(access_type_read_write);
// Create an accelerator_view from the default accelerator. The
// accelerator_view reflects the default_cpu_access_type of the
// accelerator it’s associated with.
accelerator_view acc_v = acc.default_view;
}
accelerator_view 总是反映与之相关联的 accelerator 的 default_cpu_access_type,并且它不提供接口来替代或更改它的 access_type。
更改默认加速器
可通过调用 accelerator::set_default 方法更改默认快捷键。 对于每个应用程序执行,您仅可更改默认快捷键一次,且必须在任何代码在 GPU 上执行前,对其进行更改。 用来更改加速器返回 false 所调用的所有后续函数。 如果在调用 parallel_for_each 时要使用不同的快捷键,请阅读本文的“使用多个快捷键”一节。 以下代码示例将默认快捷键设置为非模拟、未连接到显示并支持双精度的快捷键。
bool pick_accelerator()
{
std::vector<accelerator> accs = accelerator::get_all();
accelerator chosen_one;
auto result =
std::find_if(accs.begin(), accs.end(), [] (const accelerator& acc)
{
return !acc.is_emulated &&
acc.supports_double_precision &&
!acc.has_display;
});
if (result != accs.end())
chosen_one = *(result);
std::wcout << chosen_one.description << std::endl;
bool success = accelerator::set_default(chosen_one.device_path);
return success;
}
使用多个快捷键
在应用程序中使用多个快捷键的方法有两种:
您可将 accelerator_view 对象传递到调用至 parallel_for_each 方法。
可构造 array 对象,方法是使用特定的 accelerator_view 对象。 C+AMP 运行时将从 lambda 表达式中捕获的 array 对象中选取 accelerator_view 对象。
特定快捷键
三个特殊快捷键的设备路径可作为 accelerator 类的属性:
accelerator::direct3d_ref 数据成员:此单线程的快捷键使用 CPU 的软件模拟泛型图形卡。 默认情况下它用于调试;但没有用于生产,因为它比硬件快捷键慢。 此外,它只能在 DirectX SDK 和 Windows SDK 中使用,无法安装在客户的计算机中。 有关详细信息,请参阅 调试 GPU 代码。
accelerator::direct3d_warp 数据成员:此快捷键提供用于在使用流式处理 SIMD 扩展 (SSE) 的多核 CPU 上运行 C++ AMP 代码的回退解决方案。
accelerator::cpu_accelerator 数据成员:您可以使用此快捷键设置暂存数组。 无法执行 C++ AMP 代码。 有关详情,请参阅关于本机代码博客中的并行编程的 C++ AMP 上的临时数组 一文。
互操作性
C++ AMP 运行时支持 accelerator_view 类和 Direct3D ID3D11Device interface(ID3D11Device 接口)之间的互操作性。 create_accelerator_view 方法采用 IUnknown 接口并返回 accelerator_view 对象。 get_device 方法采用 accelerator_view 对象并返回 IUknown 接口。