Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
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ı işaretleme, dondurma, çözme ve gruplandırma.
- Bir karo içindeki tüm iş parçacıklarını kodda belirli bir konumda çalıştırma.
Önkoşullar
Bu açıklamalı rehbere başlamadan önce:
Not
C++ AMP üst bilgileri Visual Studio 2022 sürüm 17.0'dan itibaren kullanım dışı bırakılmıştır.
AMP üst bilgilerini dahil etmek derleme hatalarına neden olur. AMP üst bilgilerini eklemeden önce uyarıları susturmak için _SILENCE_AMP_DEPRECATION_WARNINGS tanımla.
- 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 üzere
AMPMapReducebölümünü Ad kutusuna girin ve farklı bir konum 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 başlatın.
Menü çubuğunda Dosya Yeni Proje'yi> seçin.>
Şablonlar bölmesinde Yüklü'nın altında Visual C++ öğesini seçin.
Win32 Konsol Uygulaması'nı seçin, Ad kutusuna
AMPMapReduceyazın ve ardından Tamam düğmesini seçin.İleri düğmesini seçin.
Önceden derlenmiş üst bilgi onay kutusunu temizleyin ve ardından Bitir 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 seçeneğine tıklayın.
Çözüm Gezgini'nde, AMPMapReduce için kısayol menüsünü açın ve ardından 'Özellikler'i seçin.
Özellik Sayfaları iletişim kutusunda Yapılandırma Özellikleri'nin altında, C/C++>Önceden Derlenmiş Başlıklar seçeneğini seçin.
Önceden Derlenmiş Üst Bilgi özelliği için Önceden Derlenmiş Üst Bilgileri Kullanma seçeneğini seçin ve ardından Tamam düğmesini seçin.
Menü çubuğunda Derle>Çözümü Derle'yi 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 for döngüdürreduction_sum_gpu_kernel. GPU üzerinde çalıştırılacak ağaç tabanlı paralel azaltmayı denetler.
CPU kodunda hata ayıklamak için
Çözüm Gezgini'nde, AMPMapReduce için kısayol menüsünü açın ve ardından 'Özellikler'i seçin.
Özellik Sayfaları iletişim kutusundaki Yapılandırma Özellikleri'nin altında Hata Ayıklama'yı seçin. Başlatılacak Hata Ayıklayıcı listesinde Yerel Windows Hata Ayıklayıcısı 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ıklama>Hata Ayıklamayı Başlat seçeneğini seçin.
Yereller penceresinde, 70. satırdaki kesme noktasına ulaşılana kadar
stride_sizedeğerini gözlemleyin.Menü çubuğunda Hata Ayıklama>Hata Ayıklamayı Durdur seçeneğini seçin.
GPU Kodunda Hata Ayıklama
Bu bölümde, sum_kernel_tiled işlevinde yer alan kod olan GPU kodu üzerinde nasıl hata ayıklanacağı 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'nde, AMPMapReduce için kısayol menüsünü açın ve ardından 'Ö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ıklama>Hata Ayıklamayı Başlat. 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 Hata Ayıkla>Pencereler>GPU İş Parçacıkları seçeneklerini 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 konu metin kutularını görüntülemek için Konu Genişletme Anahtarı 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 bir döşeme 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. satırda tanımlanan tile_barrier::wait ifadesinde, dört aktif GPU iş parçacığı ve 28 GPU iş parçacığı engellenmiş durumda 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ı bir ok işaretler. Farklı bir iş parçacığına geçmek için aşağıdaki yöntemlerden birini kullanın:GPU İş Parçacıkları penceresinde geçiş yapılacak iş parçacığının bulunduğu 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 Hata Ayıkla>Pencereler>Paralel Yığınlar seçeneklerini 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 Threads'in 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_stubişlev çağrısındanparallel_for_eachlambda deyimine ve ardından paralel azaltmanın gerçekleştiğisum_kernel_tiledişlevine gitti. 32 iş parçacığından 28'itile_barrier::waitdeyimine kadar ilerlemiş ve 22. satırda engellenmiş durumda kalırken, diğer dört iş parçacığı 30. satırdakisum_kernel_tiledişlevinde etkin durumda kalır.GPU iş parçacığının özelliklerini inceleyebilirsiniz. GPU İş Parçacıkları penceresinde, Paralel Yığınlar penceresinin zengin DataTip'inde mevcuttur. 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
Menü çubuğunda Debug>Windows>Parallel Watch>Parallel Watch 1 seçeneğini seçerek Parallel Watch penceresini açın.
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özlem Ekle sütun başlığını seçin,
localIdxyazın ve Enter tuşuna basın.Saat Ekle sütun üst bilgisini yeniden seçin, yazın
globalIdxve 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]] > 20000ve 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ş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ını işaretlemek için
Döşeme dizini 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 öğesini seçin; bu, etkin durumda olan dört iş parçacığının AMPMapReduce.cpp dosyasındaki 32. satırda tanımlanan bir sonraki bariyere ilerlemesine neden olur.
Ş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 işaretlenmiş 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.
İşaretlediğiniz dört iş parçacığına odaklanmak istiyorsanız, yalnızca işaretlenmiş 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.
Yalnızca İşaretlenenleri Göster düğmesini pencerelerden herhangi birinde veya Hata Ayıklama Konumu araç çubuğunda seçin. Aşağıdaki çizim, Hata Ayıklama Konumu araç çubuğundaki Yalnızca İşaretlileri Göster düğmesini gösterir.
Yalnızca işaretli olanları 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 iş parçacıklarını, ya GPU İş Parçacıkları penceresinden ya da Paralel İzleme penceresinden dondurabilir (askıya alabilir) ve çözebilirsiniz (sürdürebilirsiniz). CPU iş parçacıklarını aynı şekilde dondurup çözebilirsiniz; bilgi için bkz. Nasıl Yapılır: İş Parçacıkları Penceresini Kullanma.
GPU üzerindeki iş parçacıklarını dondurmak ve çözmek için
Yalnızca İşaretlenenleri Göster düğmesini seçerek tüm iş parçacıklarını görüntüleyin.
Menü çubuğunda Hata Ayıkla>Devam Et seçeneklerini 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.
Menü çubuğunda Hata Ayıkla>Devam Et seçeneklerini seçerek, 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 verin. 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ı penceresinde bir iş parçacığının kısayol menüsünde, Gruplandır, 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 kodundaki talimata 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 bariyerdeki talimat için hazır konumda. Bu iş parçacıklarından dördü işaretlenmiş. 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ıGruplandır işlemini, Paralel İzleme penceresinin veri tablosu için kısayol menüsünü açarak da 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 İmlece Kadar Çalıştır işlevini kullanarak, belirtilen bir kutudaki tüm iş parçacıklarını imleci içeren satıra kadar ç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 Döşemeyi İmlece Kadar Çalıştır'ı seçin.
Önceden 21. satırdaki bariyerde engellenmiş olan 24 iş parçacığı, 32. satıra ilerledi. 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