C++ AMP'ye Genel Bakış

Not

C++ AMP üst bilgileri Visual Studio 2022 sürüm 17.0'dan itibaren kullanım dışı bırakılmıştır. Tüm AMP üst bilgileri dahil olmak derleme hataları oluşturur. Uyarıları susturmak için AMP üst bilgilerini eklemeden önce tanımlayın _SILENCE_AMP_DEPRECATION_WARNINGS .

C++ Hızlandırılmış Yüksek Paralellik (C++ AMP), ayrı bir grafik kartındaki grafik işleme birimi (GPU) gibi veri paralel donanımlarından yararlanarak C++ kodunun yürütülmesini hızlandırır. C++ AMP kullanarak çok boyutlu veri algoritmaları kodlayabilirsiniz, böylece yürütme heterojen donanımlarda paralellik kullanılarak hızlandırılabilir. C++ AMP programlama modeli çok boyutlu diziler, dizin oluşturma, bellek aktarımı, döşeme ve matematiksel işlev kitaplığı içerir. Performansı geliştirebilmeniz için verilerin CPU'dan GPU'ya ve geriye nasıl taşındığını denetlemek için C++ AMP dil uzantılarını kullanabilirsiniz.

Sistem Gereksinimleri

  • Windows 7 veya üzeri

  • Visual Studio 2019 ile Windows Server 2008 R2.

  • DirectX 11 Özellik Düzeyi 11.0 veya üzeri donanım

  • Yazılım öykünücüsnde hata ayıklama için Windows 8 veya Windows Server 2012 gereklidir. Donanımda hata ayıklama için grafik kartınızın sürücülerini yüklemeniz gerekir. Daha fazla bilgi için bkz . GPU Kodunda Hata Ayıklama.

  • Not: AMP şu anda ARM64'te desteklenmiyor.

Giriş

Aşağıdaki iki örnek C++ AMP'nin birincil bileşenlerini göstermektedir. İki tek boyutlu diziye karşılık gelen öğeleri eklemek istediğinizi varsayalım. Örneğin, eklemek {1, 2, 3, 4, 5} ve {6, 7, 8, 9, 10} almak {7, 9, 11, 13, 15}isteyebilirsiniz. C++ AMP kullanmadan, sayıları eklemek ve sonuçları görüntülemek için aşağıdaki kodu yazabilirsiniz.

#include <iostream>

void StandardMethod() {

    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5];

    for (int idx = 0; idx < 5; idx++)
    {
        sumCPP[idx] = aCPP[idx] + bCPP[idx];
    }

    for (int idx = 0; idx < 5; idx++)
    {
        std::cout << sumCPP[idx] << "\n";
    }
}

Kodun önemli bölümleri şunlardır:

  • Veri: Veriler üç diziden oluşur. Tümü aynı dereceye (bir) ve uzunluğa (beş) sahiptir.

  • Yineleme: İlk for döngü, dizilerdeki öğeler arasında yinelemeye yönelik bir mekanizma sağlar. Toplamları hesaplamak için yürütmek istediğiniz kod ilk for blokta yer alır.

  • Dizin: Değişken, idx dizilerin tek tek öğelerine erişir.

Bunun yerine C++ AMP kullanarak aşağıdaki kodu yazabilirsiniz.

#include <amp.h>
#include <iostream>
using namespace concurrency;

const int size = 5;

void CppAmpMethod() {
    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[size];

    // Create C++ AMP objects.
    array_view<const int, 1> a(size, aCPP);
    array_view<const int, 1> b(size, bCPP);
    array_view<int, 1> sum(size, sumCPP);
    sum.discard_data();

    parallel_for_each(
        // Define the compute domain, which is the set of threads that are created.
        sum.extent,
        // Define the code to run on each thread on the accelerator.
        [=](index<1> idx) restrict(amp) {
            sum[idx] = a[idx] + b[idx];
        }
    );

    // Print the results. The expected output is "7, 9, 11, 13, 15".
    for (int i = 0; i < size; i++) {
        std::cout << sum[i] << "\n";
    }
}

Aynı temel öğeler vardır, ancak C++ AMP yapıları kullanılır:

  • Veri: Üç C++ AMP array_view nesnesi oluşturmak için C++ dizileri kullanırsınız. Bir array_view nesneyi oluşturmak için dört değer sağlarsınız: veri değerleri, derece, öğe türü ve her boyuttaki nesnenin array_view uzunluğu. Derece ve tür, tür parametresi olarak geçirilir. Veriler ve uzunluk oluşturucu parametreleri olarak geçirilir. Bu örnekte, oluşturucuya geçirilen C++ dizisi tek boyutludur. Derece ve uzunluk, nesnedeki array_view verilerin dikdörtgen şeklini oluşturmak için kullanılır ve veri değerleri diziyi doldurmak için kullanılır. Çalışma zamanı kitaplığı, sınıfına benzeyen bir arabirime sahip olan ve bu makalenin ilerleyen bölümlerinde ele alınan Sınıfı dizisini array_view de içerir.

  • Yineleme: parallel_for_each İşlevi (C++ AMP), veri öğeleri veya işlem etki alanı üzerinden yinelemeye yönelik bir mekanizma sağlar. Bu örnekte işlem etki alanı tarafından sum.extentbelirtilir. Yürütmek istediğiniz kod bir lambda ifadesinde veya çekirdek işlevinde yer alır. yalnızca restrict(amp) C++ AMP'nin hızlandırabileceği C++ dilinin alt kümesinin kullanıldığını gösterir.

  • Dizin: dizin Sınıfı değişkeni, idxnesnenin derecelendirmesiyle eşleşmesi için bir dereceyle array_view bildirilir. Dizini kullanarak nesnelerin tek tek öğelerine array_view erişebilirsiniz.

Verileri Şekillendirme ve Dizin Oluşturma: dizin ve kapsam

Çekirdek kodunu çalıştırabilmeniz için önce veri değerlerini tanımlamanız ve verilerin şeklini bildirmeniz gerekir. Tüm veriler bir dizi (dikdörtgen) olarak tanımlanır ve diziyi herhangi bir dereceye (boyut sayısı) sahip olacak şekilde tanımlayabilirsiniz. Veriler herhangi bir boyutta olabilir.

index Sınıfı

dizin Sınıfı, her boyuttaki array kaynaktan uzaklığı tek bir nesneye kapsülleyerek veya array_view nesnesinde bir konum belirtir. Dizideki bir konuma eriştiğinizde, tamsayı dizinleri listesi yerine dizin işlecine []bir index nesne geçirirsiniz. Array::operator() İşlecini veya array_view::operator() İşlecini kullanarak her boyuttaki öğelere erişebilirsiniz.

Aşağıdaki örnek, tek boyutlu bir nesnedeki üçüncü öğeyi belirten tek boyutlu array_view bir dizin oluşturur. Dizin, nesnedeki üçüncü öğeyi array_view yazdırmak için kullanılır. Çıkış 3'dür.

int aCPP[] = {1, 2, 3, 4, 5};
array_view<int, 1> a(5, aCPP);

index<1> idx(2);

std::cout << a[idx] << "\n";
// Output: 3

Aşağıdaki örnek, iki boyutlu bir nesnede satır = 1 ve sütun = 2 öğesini belirten iki boyutlu array_view bir dizin oluşturur. Oluşturucudaki index ilk parametre satır bileşeni, ikinci parametre ise sütun bileşenidir. Çıkış 6'dır.

int aCPP[] = {1, 2, 3, 4, 5, 6};
array_view<int, 2> a(2, 3, aCPP);

index<2> idx(1, 2);

std::cout <<a[idx] << "\n";
// Output: 6

Aşağıdaki örnek, üç boyutlu bir nesnede derinlik = 0, satır = 1 ve sütun = 3 öğesini belirten üç boyutlu array_view bir dizin oluşturur. İlk parametrenin derinlik bileşeni, ikinci parametrenin satır bileşeni ve üçüncü parametrenin sütun bileşeni olduğuna dikkat edin. Çıkış 8'dir.

int aCPP[] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

array_view<int, 3> a(2, 3, 4, aCPP);

// Specifies the element at 3, 1, 0.
index<3> idx(0, 1, 3);

std::cout << a[idx] << "\n";
// Output: 8

extent Sınıfı

Extent Sınıfı, veya array_view nesnesinin her boyutundaki array verilerin uzunluğunu belirtir. Bir kapsam oluşturabilir ve bunu kullanarak array veya array_view nesnesi oluşturabilirsiniz. Ayrıca mevcut array veya array_view nesnenin kapsamını da alabilirsiniz. Aşağıdaki örnek, bir array_view nesnenin her boyutundaki uzantının uzunluğunu yazdırır.

int aCPP[] = {
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// There are 3 rows and 4 columns, and the depth is two.
array_view<int, 3> a(2, 3, 4, aCPP);

std::cout << "The number of columns is " << a.extent[2] << "\n";
std::cout << "The number of rows is " << a.extent[1] << "\n";
std::cout << "The depth is " << a.extent[0] << "\n";
std::cout << "Length in most significant dimension is " << a.extent[0] << "\n";

Aşağıdaki örnek, önceki örnekteki nesneyle aynı boyutlara sahip bir array_view nesne oluşturur, ancak bu örnek oluşturucuda array_view açık parametreler kullanmak yerine bir extent nesne kullanır.

int aCPP[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
extent<3> e(2, 3, 4);

array_view<int, 3> a(e, aCPP);

std::cout << "The number of columns is " << a.extent[2] << "\n";
std::cout << "The number of rows is " << a.extent[1] << "\n";
std::cout << "The depth is " << a.extent[0] << "\n";

Verileri Hızlandırıcıya Taşıma: dizi ve array_view

Verileri hızlandırıcıya taşımak için kullanılan iki veri kapsayıcısı çalışma zamanı kitaplığında tanımlanır. Bunlar dizi Sınıfı ve array_view Sınıfıdır. array sınıfı, nesne oluşturulduğunda verilerin derin bir kopyasını oluşturan bir kapsayıcı sınıfıdır. array_view sınıfı, çekirdek işlevi verilere eriştiğinde verileri kopyalayan bir sarmalayıcı sınıfıdır. Kaynak cihazda veriler gerektiğinde veriler geri kopyalanır.

array Sınıfı

Bir array nesne oluşturulduğunda, veri kümesinin işaretçisini içeren bir oluşturucu kullanırsanız hızlandırıcıda verilerin derin bir kopyası oluşturulur. Çekirdek işlevi, hızlandırıcıdaki kopyayı değiştirir. Çekirdek işlevinin yürütülmesi tamamlandığında, verileri kaynak veri yapısına geri kopyalamanız gerekir. Aşağıdaki örnek bir vektördeki her öğeyi 10 ile çarpar. Çekirdek işlevi tamamlandıktan sonra, vector conversion operator verileri vektör nesnesine geri kopyalamak için kullanılır.

std::vector<int> data(5);

for (int count = 0; count <5; count++)
{
    data[count] = count;
}

array<int, 1> a(5, data.begin(), data.end());

parallel_for_each(
    a.extent,
    [=, &a](index<1> idx) restrict(amp) {
        a[idx] = a[idx]* 10;
    });

data = a;
for (int i = 0; i < 5; i++)
{
    std::cout << data[i] << "\n";
}

array_view Sınıfı

sınıfıyla array_view neredeyse aynı üyelere array sahiptir, ancak temel alınan davranış aynı değildir. Oluşturucuya array_view geçirilen veriler, oluşturucuda array olduğu gibi GPU'da çoğaltılmaz. Bunun yerine, çekirdek işlevi yürütürken veriler hızlandırıcıya kopyalanır. Bu nedenle, aynı verileri kullanan iki array_view nesne oluşturursanız, her iki nesne de array_view aynı bellek alanına başvurur. Bunu yaptığınızda, çok iş parçacıklı erişimi eşitlemeniz gerekir. sınıfını array_view kullanmanın temel avantajı, verilerin yalnızca gerekli olduğunda taşınmasıdır.

Dizi ve array_view karşılaştırması

Aşağıdaki tabloda ve array_view sınıfları arasındaki benzerlikler ve farklar özetlemektedirarray.

Açıklama array sınıfı array_view sınıfı
Derece belirlendiğinde Derleme zamanında. Derleme zamanında.
Kapsam belirlendiğinde Çalışma zamanında. Çalışma zamanında.
Şekil Dikdörtgen. Dikdörtgen.
Veri depolama Bir veri kapsayıcısıdır. Bir veri sarmalayıcıdır.
Kopyala Tanımda açık ve ayrıntılı kopya. Çekirdek işlevi tarafından erişildiğinde örtük kopya.
Veri alma Dizi verilerini CPU iş parçacığındaki bir nesneye geri kopyalayarak. Nesneye array_view doğrudan erişerek veya özgün kapsayıcıdaki verilere erişmeye devam etmek için array_view::synchronize Yöntemini çağırarak.

Dizi ve array_view ile paylaşılan bellek

Paylaşılan bellek, hem CPU hem de hızlandırıcı tarafından erişilebilen bellektir. Paylaşılan belleğin kullanılması, CPU ile hızlandırıcı arasında veri kopyalama yükünü ortadan kaldırır veya önemli ölçüde azaltır. Bellek paylaşılsa da hem CPU hem de hızlandırıcı tarafından eşzamanlı olarak erişilemez ve bunun yapılması tanımsız davranışa neden olur.

array nesneleri, ilişkili hızlandırıcı destekliyorsa paylaşılan bellek kullanımı üzerinde ayrıntılı denetim belirtmek için kullanılabilir. Hızlandırıcının paylaşılan belleği destekleyip desteklemediği, hızlandırıcının paylaşılan bellek desteklendiğinde döndüren true supports_cpu_shared_memory özelliği tarafından belirlenir. Paylaşılan bellek destekleniyorsa, hızlandırıcıdaki bellek ayırmaları için varsayılan access_type Numaralandırma özelliği tarafından default_cpu_access_type belirlenir. Varsayılan olarak array ve array_view nesneler birincil ilişkili acceleratorile aynı access_type olur.

Bir dizinin ::cpu_access_type Veri Üyesi özelliğini açıkça ayarlayarak, paylaşılan belleğin array nasıl kullanıldığı üzerinde ayrıntılı denetim kullanabilirsiniz; böylece uygulamayı hesaplama çekirdeklerinin bellek erişim desenlerine göre donanımın performans özelliklerine göre iyileştirebilirsiniz. , array_view ilişkili olduğu ortamla array aynı cpu_access_type sonucu verir veya array_view veri kaynağı olmadan oluşturulursa, access_type ilk olarak depolamayı ayırmasına neden olan ortamı yansıtır. Başka bir ifadeyle, ana bilgisayar (CPU) tarafından ilk kez erişiliyorsa, bir CPU veri kaynağı üzerinden oluşturulmuş gibi davranır ve yakalama ile ilişkili öğesini paylaşıraccess_type; ancak ilk kez bir accelerator_viewtarafından erişiliyorsa, üzerinde oluşturulan accelerator_view bir array üzerinde oluşturulmuş gibi davranır ve 'access_typeleri arrayaccelerator_view paylaşır.

Aşağıdaki kod örneği, varsayılan hızlandırıcının paylaşılan belleği destekleyip desteklemediğini belirlemeyi ve ardından farklı cpu_access_type yapılandırmalarına sahip çeşitli diziler oluşturma işlemini gösterir.

#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.default_cpu_access_type = access_type_read_write

    // Create an accelerator_view from the default accelerator. The
    // accelerator_view inherits its default_cpu_access_type from acc.
    accelerator_view acc_v = acc.default_view;

    // Create an extent object to size the arrays.
    extent<1> ex(10);

    // Input array that can be written on the CPU.
    array<int, 1> arr_w(ex, acc_v, access_type_write);

    // Output array that can be read on the CPU.
    array<int, 1> arr_r(ex, acc_v, access_type_read);

    // Read-write array that can be both written to and read from on the CPU.
    array<int, 1> arr_rw(ex, acc_v, access_type_read_write);
}

Veriler Üzerinden Kod Yürütme: parallel_for_each

parallel_for_each işlevi, veya array_view nesnesindeki array verilere karşı hızlandırıcıda çalıştırmak istediğiniz kodu tanımlar. Bu konunun girişinden aşağıdaki kodu göz önünde bulundurun.

#include <amp.h>
#include <iostream>
using namespace concurrency;

void AddArrays() {
    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5] = {0, 0, 0, 0, 0};

    array_view<int, 1> a(5, aCPP);
    array_view<int, 1> b(5, bCPP);
    array_view<int, 1> sum(5, sumCPP);

    parallel_for_each(
        sum.extent,
        [=](index<1> idx) restrict(amp)
        {
            sum[idx] = a[idx] + b[idx];
        }
    );

    for (int i = 0; i < 5; i++) {
        std::cout << sum[i] << "\n";
    }
}

parallel_for_each yöntemi, işlem etki alanı ve lambda ifadesi olmak üzere iki bağımsız değişken alır.

İşlem etki alanı , paralel yürütme için oluşturulacak iş parçacıkları kümesini tanımlayan bir extent tiled_extent nesne veya nesnedir. İşlem etki alanındaki her öğe için bir iş parçacığı oluşturulur. Bu durumda, extent nesne tek boyutludur ve beş öğeye sahiptir. Bu nedenle, beş iş parçacığı başlatılır.

Lambda ifadesi, her iş parçacığında çalıştırılacak kodu tanımlar. capture yan tümcesi, [=]lambda ifadesinin gövdesinin yakalanan tüm değişkenlere değere göre erişdiğini belirtir. Bu durumda , bve sumolura. Bu örnekte parametre listesi adlı idxtek boyutlu index bir değişken oluşturur. değerinin idx[0] değeri ilk iş parçacığında 0'dır ve sonraki her iş parçacığında bir artar. yalnızca restrict(amp) C++ AMP'nin hızlandırabileceği C++ dilinin alt kümesinin kullanıldığını gösterir. Kısıtlayıcı değiştiricisine sahip işlevlerle ilgili sınırlamalar restrict (C++ AMP) bölümünde açıklanmıştır. Daha fazla bilgi için bkz . Lambda İfade söz dizimi.

Lambda ifadesi yürütülecek kodu içerebilir veya ayrı bir çekirdek işlevi çağırabilir. Çekirdek işlevi değiştiriciyi restrict(amp) içermelidir. Aşağıdaki örnek önceki örneğe eşdeğerdir, ancak ayrı bir çekirdek işlevi çağırır.

#include <amp.h>
#include <iostream>
using namespace concurrency;

void AddElements(
    index<1> idx,
    array_view<int, 1> sum,
    array_view<int, 1> a,
    array_view<int, 1> b) restrict(amp) {
    sum[idx] = a[idx] + b[idx];
}

void AddArraysWithFunction() {

    int aCPP[] = {1, 2, 3, 4, 5};
    int bCPP[] = {6, 7, 8, 9, 10};
    int sumCPP[5] = {0, 0, 0, 0, 0};

    array_view<int, 1> a(5, aCPP);
    array_view<int, 1> b(5, bCPP);
    array_view<int, 1> sum(5, sumCPP);

    parallel_for_each(
        sum.extent,
        [=](index<1> idx) restrict(amp) {
            AddElements(idx, sum, a, b);
        }
    );

    for (int i = 0; i < 5; i++) {
        std::cout << sum[i] << "\n";
    }
}

Kodu Hızlandırma: Kutucuklar ve Engeller

Döşeme kullanarak ek hızlandırma kazanabilirsiniz. Döşeme, iş parçacıklarını eşit dikdörtgen alt kümelere veya kutucuklara böler. Veri kümenize ve kodladığınız algoritmaya göre uygun kutucuk boyutunu belirlersiniz. Her iş parçacığı için, bir veri öğesinin tamamına array göre genel konumuna veya array_view kutucuğa göre yerel konuma erişiminiz vardır. Yerel dizin değerinin kullanılması kodunuzu basitleştirir çünkü dizin değerlerini genelden yerele çevirmek için kodu yazmanız gerekmez. Döşeme kullanmak için yöntemindeki işlem etki alanında parallel_for_each extent::tile Yöntemini çağırın ve lambda ifadesinde bir tiled_index nesnesi kullanın.

Tipik uygulamalarda kutucuktaki öğeler bir şekilde ilişkilidir ve kodun kutucuktaki değerlere erişmesi ve değerleri izlemesi gerekir. Bunu yapmak için tile_static Anahtar Sözcüğü anahtar sözcüğünü ve tile_barrier::wait Yöntemini kullanın. tile_static anahtar sözcüğüne sahip bir değişkenin kapsamı kutucuğun tamamındadır ve her kutucuk için değişkenin bir örneği oluşturulur. Değişkene kutucuk iş parçacığı erişimini eşitlemeyi işlemeniz gerekir. tile_barrier::wait Yöntemi, kutucuktaki tüm iş parçacıkları çağrısına ulaşana kadar geçerli iş parçacığının yürütülmesini tile_barrier::waitdurdurur. Böylece tile_static değişkenleri kullanarak kutucuk genelinde değerleri biriktirebilirsiniz. Ardından tüm değerlere erişim gerektiren tüm hesaplamaları tamamlayabilirsiniz.

Aşağıdaki diyagram, kutucuklar halinde yerleştirilmiş iki boyutlu örnekleme verilerini temsil eder.

Kutucuklu bir kapsamdaki dizin değerleri.

Aşağıdaki kod örneği, önceki diyagramdaki örnekleme verilerini kullanır. Kod, kutucuktaki her değeri kutucuktaki değerlerin ortalaması ile değiştirir.

// Sample data:
int sampledata[] = {
    2, 2, 9, 7, 1, 4,
    4, 4, 8, 8, 3, 4,
    1, 5, 1, 2, 5, 2,
    6, 8, 3, 2, 7, 2};

// The tiles:
// 2 2    9 7    1 4
// 4 4    8 8    3 4
//
// 1 5    1 2    5 2
// 6 8    3 2    7 2

// Averages:
int averagedata[] = {
    0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0,
};

array_view<int, 2> sample(4, 6, sampledata);

array_view<int, 2> average(4, 6, averagedata);

parallel_for_each(
    // Create threads for sample.extent and divide the extent into 2 x 2 tiles.
    sample.extent.tile<2,2>(),
        [=](tiled_index<2,2> idx) restrict(amp) {
        // Create a 2 x 2 array to hold the values in this tile.
        tile_static int nums[2][2];

        // Copy the values for the tile into the 2 x 2 array.
        nums[idx.local[1]][idx.local[0]] = sample[idx.global];

        // When all the threads have executed and the 2 x 2 array is complete, find the average.
        idx.barrier.wait();
        int sum = nums[0][0] + nums[0][1] + nums[1][0] + nums[1][1];

        // Copy the average into the array_view.
        average[idx.global] = sum / 4;
    });

for (int i = 0; i <4; i++) {
    for (int j = 0; j <6; j++) {
        std::cout << average(i,j) << " ";
    }
    std::cout << "\n";
}

// Output:
// 3 3 8 8 3 3
// 3 3 8 8 3 3
// 5 5 2 2 4 4
// 5 5 2 2 4 4

Matematik Kitaplıkları

C++ AMP iki matematik kitaplığı içerir. Concurrency::p recise_math Ad Alanı'ndaki çift duyarlıklı kitaplık, çift duyarlıklı işlevler için destek sağlar. Ayrıca tek duyarlıklı işlevler için destek sağlar, ancak donanımda çift duyarlık desteği hala gereklidir. C99 Belirtimine (ISO/IEC 9899) uygundur. Hızlandırıcı tam çift duyarlık desteklemelidir. Hızlandırıcının değerini denetleyerek olup olmadığını belirleyebilirsiniz::supports_double_precision Veri Üyesi. Concurrency::fast_math Ad Alanındaki hızlı matematik kitaplığı başka bir matematik işlevi kümesi içerir. Yalnızca float işlenenleri destekleyen bu işlevler daha hızlı yürütülür ancak çift duyarlıklı matematik kitaplığındakiler kadar kesin değildir. İşlevler amp_math.h> üst bilgi dosyasında bulunur <ve tümü ile restrict(amp)bildirilir. cmath> üst bilgi dosyasındaki <işlevler hem hem precise_math de fast_math ad alanlarına aktarılır. restrict anahtar sözcüğü, cmath> sürümünü ve C++ AMP sürümünü ayırt <etmek için kullanılır. Aşağıdaki kod, işlem etki alanındaki her değerin hızlı yöntemini kullanarak 10 tabanındaki logaritması hesaplar.

#include <amp.h>
#include <amp_math.h>
#include <iostream>
using namespace concurrency;

void MathExample() {

    double numbers[] = { 1.0, 10.0, 60.0, 100.0, 600.0, 1000.0 };
    array_view<double, 1> logs(6, numbers);

    parallel_for_each(
        logs.extent,
        [=] (index<1> idx) restrict(amp) {
            logs[idx] = concurrency::fast_math::log10(numbers[idx]);
        }
    );

    for (int i = 0; i < 6; i++) {
        std::cout << logs[i] << "\n";
    }
}

Grafik Kitaplığı

C++ AMP, hızlandırılmış grafik programlama için tasarlanmış bir grafik kitaplığı içerir. Bu kitaplık yalnızca yerel grafik işlevselliğini destekleyen cihazlarda kullanılır. Yöntemler Concurrency::graphics Ad Alanındadır ve amp_graphics.h> üst bilgi dosyasında bulunur<. Grafik kitaplığının temel bileşenleri şunlardır:

  • texture Sınıfı: Doku sınıfını kullanarak bellekten veya dosyadan doku oluşturabilirsiniz. Dokular veri içerdiğinden dizilere benzer ve atama ve kopyalama yapısı bakımından C++ Standart Kitaplığı'ndaki kapsayıcılara benzer. Daha fazla bilgi için bkz . C++ Standart Kitaplık Kapsayıcıları. sınıfı için texture şablon parametreleri öğe türü ve derecedir. Derece 1, 2 veya 3 olabilir. Öğe türü, bu makalenin devamında açıklanan kısa vektör türlerinden biri olabilir.

  • writeonly_texture_view Sınıfı: Herhangi bir dokuya salt yazma erişimi sağlar.

  • Kısa Vektör Kitaplığı: , doublefloatuintnorm veya unorm tabanlı int2, 3 ve 4 uzunluğundaki kısa vektör türlerini tanımlar.

Evrensel Windows Platformu (UWP) Uygulamaları

Diğer C++ kitaplıklarında olduğu gibi UWP uygulamalarınızda da C++ AMP kullanabilirsiniz. Bu makalelerde C++, C#, Visual Basic veya JavaScript kullanılarak oluşturulan uygulamalara C++ AMP kodunun nasıl dahil olduğu açıklanmaktadır:

C++ AMP ve Eşzamanlılık Görselleştiricisi

Eşzamanlılık Görselleştiricisi, C++ AMP kodunun performansını analiz etme desteği içerir. Bu makalelerde şu özellikler açıklanmaktadır:

Performans Önerileri

Modüller ve işaretsiz tamsayıların bölünmesi, modülden ve imzalı tamsayıların bölünmesinden önemli ölçüde daha iyi performansa sahiptir. Mümkün olduğunda işaretsiz tamsayılar kullanmanızı öneririz.

Ayrıca bkz.

C++ AMP (C++ Accelerated Massive Parallelism)
Lambda İfadesi Söz Dizimi
Başvuru (C++ AMP)
Yerel Kodda Paralel Programlama Blogu