İzlenecek yol: C++ AMP uygulamasında hata ayıklama
Bu makalede, grafik işleme biriminden (GPU) yararlanmak için C++ Hızlandırılmış Yüksek Paralellik (C++ AMP) kullanan bir uygulamada hata ayıklama işlemi gösterilmektedir. Büyük bir tamsayı dizisini toplayan paralel azaltma programı kullanır. Bu izlenecek yol aşağıdaki görevleri gösterir:
- GPU hata ayıklayıcısını başlatma.
- GPU İş Parçacıkları penceresinde GPU iş parçacıklarını inceleme.
- Birden çok GPU iş parçacığının çağrı yığınlarını aynı anda gözlemlemek için Paralel Yığınlar penceresini kullanma.
- Birden çok iş parçacığındaki tek bir ifadenin değerlerini aynı anda incelemek için Paralel İzleme penceresini kullanma.
- GPU iş parçacıklarını bayraklama, dondurma, çözme ve gruplandırma.
- Bir kutucuğun tüm iş parçacıklarını koddaki belirli bir konuma yürütme.
Önkoşullar
Bu izlenecek yolu başlatmadan önce:
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++ AMP'ye Genel Bakış'a bakın.
- Metin düzenleyicisinde satır numaralarının görüntülendiğinden emin olun. Daha fazla bilgi için bkz . Nasıl yapılır: Düzenleyicide satır numaralarını görüntüleme.
- Yazılım öykünücüsnde hata ayıklamayı desteklemek için en az Windows 8 veya Windows Server 2012 çalıştırdığınızdan emin olun.
Not
Bilgisayarınız, aşağıdaki yönergelerde yer alan Visual Studio kullanıcı arabirimi öğelerinden bazıları için farklı adlar veya konumlar gösterebilir. Sahip olduğunuz Visual Studio sürümü ve kullandığınız ayarlar bu öğeleri belirler. Daha fazla bilgi için bkz. IDE’yi kişiselleştirme.
Örnek projeyi oluşturmak için
Proje oluşturma yönergeleri, hangi Visual Studio sürümünü kullandığınıza bağlı olarak değişir. Bu sayfadaki içindekiler tablosunun üzerinde doğru belge sürümünü seçtiğinizden emin olun.
Visual Studio'da örnek proje oluşturmak için
Menü çubuğunda Dosya Yeni Proje'yi seçerek >Yeni>Proje Oluştur iletişim kutusunu açın.
İletişim kutusunun üst kısmında Dil'i C++ olarak, Platform'ı Windows olarak ve Proje türü'nü Konsol olarak ayarlayın.
Filtrelenen proje türleri listesinden Konsol Uygulaması'nı ve ardından İleri'yi seçin. Sonraki sayfada, proje için bir ad belirtmek için Ad kutusuna girin
AMPMapReduce
ve farklı bir ad istiyorsanız proje konumunu belirtin.İstemci projesini oluşturmak için Oluştur düğmesini seçin.
Visual Studio 2017 veya Visual Studio 2015'te örnek proje oluşturmak için
Visual Studio’yu çalıştırın.
Menü çubuğunda Dosya Yeni Proje'yi> seçin.>
Şablonlar bölmesinde yüklü'nin altında Visual C++ öğesini seçin.
Win32 Konsol Uygulaması'nı seçin, Ad kutusuna yazın
AMPMapReduce
ve ardından Tamam düğmesini seçin.İleri düğmesini seçin.
Önceden derlenmiş üst bilgi onay kutusunu temizleyin ve son düğmesini seçin.
Çözüm Gezgini stdafx.h, targetver.h ve stdafx.cpp projeden silin.
İleri:
AMPMapReduce.cpp açın ve içeriğini aşağıdaki kodla değiştirin.
// AMPMapReduce.cpp defines the entry point for the program. // The program performs a parallel-sum reduction that computes the sum of an array of integers. #include <stdio.h> #include <tchar.h> #include <amp.h> const int BLOCK_DIM = 32; using namespace concurrency; void sum_kernel_tiled(tiled_index<BLOCK_DIM> t_idx, array<int, 1> &A, int stride_size) restrict(amp) { tile_static int localA[BLOCK_DIM]; index<1> globalIdx = t_idx.global * stride_size; index<1> localIdx = t_idx.local; localA[localIdx[0]] = A[globalIdx]; t_idx.barrier.wait(); // Aggregate all elements in one tile into the first element. for (int i = BLOCK_DIM / 2; i > 0; i /= 2) { if (localIdx[0] < i) { localA[localIdx[0]] += localA[localIdx[0] + i]; } t_idx.barrier.wait(); } if (localIdx[0] == 0) { A[globalIdx] = localA[0]; } } int size_after_padding(int n) { // The extent might have to be slightly bigger than num_stride to // be evenly divisible by BLOCK_DIM. You can do this by padding with zeros. // The calculation to do this is BLOCK_DIM * ceil(n / BLOCK_DIM) return ((n - 1) / BLOCK_DIM + 1) * BLOCK_DIM; } int reduction_sum_gpu_kernel(array<int, 1> input) { int len = input.extent[0]; //Tree-based reduction control that uses the CPU. for (int stride_size = 1; stride_size < len; stride_size *= BLOCK_DIM) { // Number of useful values in the array, given the current // stride size. int num_strides = len / stride_size; extent<1> e(size_after_padding(num_strides)); // The sum kernel that uses the GPU. parallel_for_each(extent<1>(e).tile<BLOCK_DIM>(), [&input, stride_size] (tiled_index<BLOCK_DIM> idx) restrict(amp) { sum_kernel_tiled(idx, input, stride_size); }); } array_view<int, 1> output = input.section(extent<1>(1)); return output[0]; } int cpu_sum(const std::vector<int> &arr) { int sum = 0; for (size_t i = 0; i < arr.size(); i++) { sum += arr[i]; } return sum; } std::vector<int> rand_vector(unsigned int size) { srand(2011); std::vector<int> vec(size); for (size_t i = 0; i < size; i++) { vec[i] = rand(); } return vec; } array<int, 1> vector_to_array(const std::vector<int> &vec) { array<int, 1> arr(vec.size()); copy(vec.begin(), vec.end(), arr); return arr; } int _tmain(int argc, _TCHAR* argv[]) { std::vector<int> vec = rand_vector(10000); array<int, 1> arr = vector_to_array(vec); int expected = cpu_sum(vec); int actual = reduction_sum_gpu_kernel(arr); bool passed = (expected == actual); if (!passed) { printf("Actual (GPU): %d, Expected (CPU): %d", actual, expected); } printf("sum: %s\n", passed ? "Passed!" : "Failed!"); getchar(); return 0; }
Menü çubuğunda Dosya>Tümünü Kaydet'i seçin.
Çözüm Gezgini,AMPMapReduce kısayol menüsünü açın ve özellikler'i seçin.
Özellik Sayfaları iletişim kutusundaki Yapılandırma Özellikleri'nin altında C/C++>Önceden Derlenmiş Üst Bilgiler'i seçin.
Önceden Derlenmiş Üst Bilgi özelliği için, Önceden Derlenmiş Üst Bilgileri Kullanma'yı seçin ve ardından Tamam düğmesini seçin.
Menü çubuğunda Derleme Çözümü Oluştur'u>seçin.
CPU Kodunda Hata Ayıklama
Bu yordamda, bu uygulamadaki CPU kodunun doğru olduğundan emin olmak için Yerel Windows Hata Ayıklayıcısı'nı kullanacaksınız. Bu uygulamadaki CPU kodunun özellikle ilginç olan bölümü işlevdeki reduction_sum_gpu_kernel
döngüdürfor
. GPU üzerinde çalıştırılacak ağaç tabanlı paralel azaltmayı denetler.
CPU kodunda hata ayıklamak için
Çözüm Gezgini,AMPMapReduce kısayol menüsünü açın ve özellikler'i seçin.
Özellik Sayfaları iletişim kutusundaki Yapılandırma Özellikleri'nin altında Hata Ayıklama'yı seçin. Başlatilecek Hata Ayıklayıcı listesinde Yerel Windows Hata Ayıklayıcısı'nın seçili olduğunu doğrulayın.
Kod Düzenleyicisi'ne dönün.
Aşağıdaki çizimde gösterilen kod satırlarında kesme noktaları ayarlayın (yaklaşık satır 67 satır 70).
CPU kesme noktalarıMenü çubuğunda Hata AyıklamaYı>Başlat Hata Ayıklama'yı seçin.
Yerel Ayarlar penceresinde, 70. satırdaki kesme noktasına ulaşılana kadar değerini
stride_size
gözlemleyin.Menü çubuğunda Hata AyıklamaYı>Durdur Hata Ayıklama'yı seçin.
GPU Kodunda Hata Ayıklama
Bu bölümde, işlevde yer alan kod olan GPU kodunda hata ayıklama işlemi sum_kernel_tiled
gösterilmektedir. GPU kodu, her "blok" için tamsayıların toplamını paralel olarak hesaplar.
GPU kodunda hata ayıklamak için
Çözüm Gezgini,AMPMapReduce kısayol menüsünü açın ve özellikler'i seçin.
Özellik Sayfaları iletişim kutusundaki Yapılandırma Özellikleri'nin altında Hata Ayıklama'yı seçin.
Başlatacak Hata Ayıklayıcı listesinde Yerel Windows Hata Ayıklayıcısı'nı seçin.
Hata Ayıklayıcı Türü listesinde Otomatik'in seçili olduğunu doğrulayın.
Otomatik varsayılan değerdir. Windows 10'un önceki sürümlerinde, Otomatik yerine Yalnızca GPU gerekli değerdir.
Tamam düğmesini seçin.
Aşağıdaki çizimde gösterildiği gibi 30. satırda bir kesme noktası ayarlayın.
GPU kesme noktasıMenü çubuğunda Hata AyıklamaYı>Başlat Hata Ayıklama'yı seçin. CPU kodundaki 67 ve 70. satırlardaki kesme noktaları GPU hata ayıklaması sırasında yürütülemez çünkü bu kod satırları CPU üzerinde çalıştırılır.
GPU İş Parçacıkları penceresini kullanmak için
GPU İş Parçacıkları penceresini açmak için menü çubuğunda Windows>GPU İş Parçacıklarında Hata Ayıklama'yı>seçin.
Görüntülenen GPU İş Parçacıkları penceresinde GPU iş parçacıklarının durumunu inceleyebilirsiniz.
GPU İş Parçacıkları penceresini Visual Studio'nun altına sabitleyin. Kutucuğu ve iş parçacığı metin kutularını görüntülemek için İş Parçacığı Anahtarını Genişlet düğmesini seçin. GPU İş Parçacıkları penceresi, aşağıdaki çizimde gösterildiği gibi toplam etkin ve engellenen GPU iş parçacığı sayısını gösterir.
GPU İş Parçacıkları penceresiBu hesaplama için 313 kutucuk ayrılır. Her kutucuk 32 iş parçacığı içerir. Yerel GPU hata ayıklaması bir yazılım öykünücüsnde gerçekleştiği için dört etkin GPU iş parçacığı vardır. Dört iş parçacığı yönergeleri aynı anda yürütür ve bir sonraki yönergeye birlikte devam eder.
GPU İş Parçacıkları penceresinde, yaklaşık 21
t_idx.barrier.wait();
. satırda tanımlanan tile_barrier::wait deyiminde engellenen dört GPU iş parçacığı ve 28 GPU iş parçacığı vardır. 32 GPU iş parçacığının tümü ilk kutucuğa aittir:tile[0]
. Geçerli iş parçacığını içeren satırı gösteren bir ok. Farklı bir iş parçacığına geçmek için aşağıdaki yöntemlerden birini kullanın:GPU İş Parçacıkları penceresinde iş parçacığının geçişine yönelik satırda, kısayol menüsünü açın ve İş Parçacığına Geç'i seçin. Satır birden fazla iş parçacığını temsil ederse, iş parçacığı koordinatlarına göre ilk iş parçacığına geçersiniz.
İlgili metin kutularına yazışmanın kutucuk ve iş parçacığı değerlerini girin ve ardından İş Parçacığını Değiştir düğmesini seçin.
Çağrı Yığını penceresi, geçerli GPU iş parçacığının çağrı yığınını görüntüler.
Paralel Yığınlar penceresini kullanmak için
Paralel Yığınlar penceresini açmak için menü çubuğunda Windows>Paralel Yığınlarında Hata Ayıklama'yı>seçin.
Birden çok GPU iş parçacığının yığın çerçevelerini aynı anda incelemek için Paralel Yığınlar penceresini kullanabilirsiniz.
Paralel Yığınlar penceresini Visual Studio'nun altına sabitleyin.
Sol üst köşedeki listede İş Parçacıkları'nın seçili olduğundan emin olun. Aşağıdaki çizimde Paralel Yığınlar penceresi, GPU İş Parçacıkları penceresinde gördüğünüz GPU iş parçacıklarının çağrı yığını odaklı görünümünü gösterir.
Paralel Yığınlar penceresi32 iş parçacığı,
_kernel_stub
işlev çağrısındaparallel_for_each
lambda deyimine ve ardından paralel azaltmanınsum_kernel_tiled
gerçekleştiği işleve gitti. 32 iş parçacığından 28'i deyiminetile_barrier::wait
ilerlemiş ve 22. satırda engellenmiş durumda kalırken, diğer dört iş parçacığı 30. satırdaki işlevdesum_kernel_tiled
etkin kalır.GPU iş parçacığının özelliklerini inceleyebilirsiniz. Bunlar, Paralel Yığınlar penceresinin zengin Veri İpucu'ndaki GPU İş Parçacıkları penceresinde kullanılabilir. Bunları görmek için işaretçiyi öğesinin yığın çerçevesinin
sum_kernel_tiled
üzerine getirin. Aşağıdaki çizimde Veri İpucu gösterilmektedir.
GPU iş parçacığı Veri İpucuParalel Yığınlar penceresi hakkında daha fazla bilgi için bkz. Paralel Yığınlar Penceresini Kullanma.
Paralel İzleme penceresini kullanmak için
Parallel Watch penceresini açmak için menü çubuğunda Windows>Parallel Watch Parallel Watch>1'de Hata Ayıklama'yı>seçin.
Birden çok iş parçacığında bir ifadenin değerlerini incelemek için Paralel İzleme penceresini kullanabilirsiniz.
Parallel Watch 1 penceresini Visual Studio'nun altına sabitleyin. Paralel İzleme penceresinin tablosunda 32 satır vardır. Her bir iş parçacığı hem GPU İş Parçacıkları penceresinde hem de Paralel Yığınlar penceresinde görünen bir GPU iş parçacığına karşılık gelir. Artık 32 GPU iş parçacığında değerlerini incelemek istediğiniz ifadeleri girebilirsiniz.
gözcü sütunu ekle üst bilgisini seçin, yazın
localIdx
ve enter tuşunu seçin.Saat Ekle sütun üst bilgisini yeniden seçin, yazın
globalIdx
ve enter tuşunu seçin.Saat Ekle sütun üst bilgisini yeniden seçin, yazın
localA[localIdx[0]]
ve enter tuşunu seçin.Belirtilen bir ifadeye göre, ilgili sütun üst bilgisini seçerek sıralama yapabilirsiniz.
Sütunu sıralamak için localA[localIdx[0]] sütun başlığını seçin. Aşağıdaki çizimde localA[localIdx[0]] ölçütüne göre sıralamanın sonuçları gösterilmektedir.
Sıralama sonuçlarıParalel İzleme penceresindeki içeriği Excel'e aktarmak için Excel düğmesini ve ardından Excel'de Aç'ı seçebilirsiniz. Geliştirme bilgisayarınızda Excel yüklüyse, düğme içeriği içeren bir Excel çalışma sayfası açar.
Paralel İzleme penceresinin sağ üst köşesinde, Boole ifadelerini kullanarak içeriği filtrelemek için kullanabileceğiniz bir filtre denetimi vardır. Filtre denetimi metin kutusuna girin
localA[localIdx[0]] > 20000
ve Enter tuşunu seçin.Pencere artık yalnızca değerin 20000'den büyük olduğu
localA[localIdx[0]]
iş parçacıklarını içerir. İçerik yine de daha önce seçtiğiniz sıralama eylemi olan sütuna görelocalA[localIdx[0]]
sıralanır.
GPU İş Parçacıklarını Etiketleme
Belirli GPU iş parçacıklarını GPU İş Parçacıkları penceresinde, Paralel İzleme penceresinde veya Paralel Yığınlar penceresindeki Veri İpucu'nda işaretleyerek işaretleyebilirsiniz. GPU İş Parçacıkları penceresindeki bir satırda birden fazla iş parçacığı varsa, bu satırın bayrakla işaretlenmesi satırda yer alan tüm iş parçacıklarına bayrak ekler.
GPU iş parçacıklarına bayrak eklemek için
Kutucuk dizinine ve iş parçacığı dizinine göre sıralamak için Parallel Watch 1 penceresinde [thread] sütun başlığını seçin.
Menü çubuğunda Hata Ayıklama Devamı'nı> seçin; bu da etkin olan dört iş parçacığının bir sonraki engele ilerlemesine neden olur (AMPMapReduce.cpp 32. satırda tanımlanır).
Şimdi etkin olan dört iş parçacığını içeren satırın sol tarafındaki bayrak simgesini seçin.
Aşağıdaki çizimde GPU İş Parçacıkları penceresindeki dört etkin bayrak eklenmiş iş parçacığı gösterilmektedir .
GPU İş Parçacıkları penceresindeki etkin iş parçacıklarıParalel İzleme penceresi ve Paralel Yığınlar penceresinin Veri İpucu, bayrak eklenmiş iş parçacıklarını gösterir.
Bayrak eklediğiniz dört iş parçacığına odaklanmak istiyorsanız, yalnızca bayrak eklenmiş iş parçacıklarını göstermeyi seçebilirsiniz. GPU İş Parçacıkları, Paralel İzleme ve Paralel Yığınlar pencerelerinde gördüklerinizi sınırlar.
Pencerelerden herhangi birinde veya Hata Ayıklama Konumu araç çubuğunda Yalnızca Bayrak Eklenmişi Göster düğmesini seçin. Aşağıdaki çizimde, Hata Ayıklama Konumu araç çubuğundaki Yalnızca Bayrak eklenmişi Göster düğmesi gösterilmektedir.
Yalnızca Bayrak eklenmiş düğmeyi gösterArtık GPU İş Parçacıkları, Paralel İzleme ve Paralel Yığınlar pencereleri yalnızca bayrak eklenmiş iş parçacıklarını görüntüler.
GPU İş Parçacıklarını Dondurma ve Çözme
GPU İş Parçacıkları penceresinden veya Paralel İzleme penceresinden GPU iş parçacıklarını dondurabilir (askıya alabilir) ve çözebilirsiniz (sürdürebilirsiniz). CPU iş parçacıklarını aynı şekilde dondurabilir ve çözebilirsiniz; bilgi için bkz . Nasıl yapılır: İş Parçacıkları Penceresini Kullanma.
GPU iş parçacıklarını dondurmak ve çözmek için
Tüm iş parçacıklarını görüntülemek için Yalnızca Bayrak Eklenmişi Göster düğmesini seçin.
Menü çubuğunda Devam Hatalarını Ayıkla'yı>seçin.
Etkin satırın kısayol menüsünü açın ve Dondur'u seçin.
GPU İş Parçacıkları penceresinin aşağıdaki çiziminde dört iş parçacığının da dondurulduğunu görebilirsiniz.
GPU İş Parçacıkları penceresinde donmuş iş parçacıklarıBenzer şekilde, Parallel Watch penceresi dört iş parçacığının da dondurulduğunu gösterir.
Sonraki dört GPU iş parçacığının 22. satırdaki engeli aşmasına ve 30. satırdaki kesme noktasına ulaşmasına izin vermek için menü çubuğunda Hata Ayıkla>Devam'ı seçin. GPU İş Parçacıkları penceresi, önceden dondurulan dört iş parçacığının donmuş ve etkin durumda kaldığını gösterir.
Menü çubuğunda Hata Ayıkla, Devam'ı seçin.
Paralel İzleme penceresinden tek tek veya birden çok GPU iş parçacığını da çözebilirsiniz.
GPU iş parçacıklarını gruplandırmak için
GPU İş Parçacıkları penceresindeki iş parçacıklarından birinin kısayol menüsünde Gruplandırma Ölçütü, Adres'i seçin.
GPU İş Parçacıkları penceresindeki iş parçacıkları adrese göre gruplandırılır. Adres, her iş parçacığı grubunun bulunduğu ayrıştırma yönergesine karşılık gelir. 24 iş parçacığı, tile_barrier::wait Yönteminin yürütüldüğü 22. satırdadır. 12 iş parçacığı, 32. satırdaki bariyer için talimattadır. Bu iş parçacıklarından dördü işaretlenir. 30. satırdaki kesme noktasında sekiz iş parçacığı vardır. Bu ipliklerden dördü donduruldu. Aşağıdaki çizimde GPU İş Parçacıkları penceresinde gruplandırılmış iş parçacıkları gösterilmektedir .
GPU İş Parçacıkları penceresinde gruplandırılmış iş parçacıklarıParalel İzleme penceresinin veri kılavuzu için kısayol menüsünü açarak Gruplandırma Ölçütü işlemini de yapabilirsiniz. Gruplandır'ı seçin ve ardından iş parçacıklarını nasıl gruplandırmak istediğinize karşılık gelen menü öğesini seçin.
Koddaki Belirli Bir Konuma Tüm İş Parçacıklarını Çalıştırma
Geçerli Kutucuğu İmleç için Çalıştır'ı kullanarak belirli bir kutucuktaki tüm iş parçacıklarını imleci içeren satıra çalıştırırsınız.
İmleç tarafından işaretlenen konuma tüm iş parçacıklarını çalıştırmak için
Dondurulmuş iş parçacıklarının kısayol menüsünde Çöz'e tıklayın.
Kod Düzenleyicisi'nde imleci 30. satıra getirin.
Kod Düzenleyicisi'nin kısayol menüsünde Geçerli Kutucuğu İmleç olarak Çalıştır'ı seçin.
Daha önce 21. satırdaki bariyerde engellenen 24 iş parçacığı 32. satıra ilerlemiş. GPU İş Parçacıkları penceresinde gösterilir.
Ayrıca bkz.
C++ AMP'ye genel bakış
GPU kodunda hata ayıklama
Nasıl yapılır: GPU İş Parçacıkları penceresini kullanma
Nasıl yapılır: Paralel İzleme penceresini kullanma
Eşzamanlılık Görselleştiricisi ile C++ AMP kodunu çözümleme