使用 accelerator 和 accelerator_view 对象

您可使用快捷键accelerator_view 类来指定设备或仿真器以运行 C++ AMP 代码。 系统可能有由内存量、共享内存支持、调试支持或双精度支持不同的多台计算机或模拟器。 C++ Accelerated Massive Parallelism (C++ AMP) 提供您能使用的 API 来检查可用的加速器,设置一个默认加速器,指定对parallel_for_each 的多个调用的多个加速器视图,并执行特殊调试任务。

使用默认快捷键

除非您编写代码选择特定快捷键,否则 C++ AMP 运行时会选择默认快捷键。 运行时选择如下所示的默认值快捷键:

  1. 如果应用程序正在运行调试模式而支持调试的加速器。

  2. 否则,则为 CPPAMP_DEFAULT_ACCELERATOR 环境变量指定的快捷键,如果已设置的话。

  3. 否则,则为非模拟的计算机。

  4. 否则,则为具有的最大数量可用内存的计算机。

  5. 否则,则为未附加到该显示屏的计算机。

此外,运行时为默认快捷键指定了 access_type_autoaccess_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 总是反映与之相关联的 acceleratordefault_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 类的属性:

互操作性

C++ AMP 运行时支持 accelerator_view 类和 Direct3D ID3D11Device interface(ID3D11Device 接口)之间的互操作性。 create_accelerator_view 方法采用 IUnknown 接口并返回 accelerator_view 对象。 get_device 方法采用 accelerator_view 对象并返回 IUknown 接口。

请参见

参考

accelerator 类

accelerator_view 类

其他资源

C++ AMP (C++ Accelerated Massive Parallelism)

调试 GPU 代码