Hızlandırıcı arka uçları

Bir Tensor hesaplamasını açıklamak oldukça basittir, ancak bu hesaplamanın ne zaman ve nasıl gerçekleştirileceği, Tensor için hangi arka ucun kullanıldığına ve sonuçların ana bilgisayar CPU'sunda ne zaman gerekli olduğuna bağlı olacaktır.

Perde arkasında, Tensor işlemler GPU'lar veya TPU'lar gibi hızlandırıcılara gönderilir veya hızlandırıcı bulunmadığında CPU üzerinde çalıştırılır. Bu sizin için otomatik olarak gerçekleşir ve üst düzey bir arayüz kullanarak karmaşık paralel hesaplamaları gerçekleştirmeyi kolaylaştırır. Ancak bu gönderimin nasıl gerçekleştiğini anlamak ve bunu en iyi performans için özelleştirebilmek yararlı olabilir.

Swift for TensorFlow, hızlandırılmış hesaplama gerçekleştirmek için iki arka uca sahiptir: TensorFlow istekli modu ve X10. Varsayılan arka uç TensorFlow istekli modudur ancak bu geçersiz kılınabilir. Bu farklı arka uçların kullanımı konusunda size yol gösterecek etkileşimli bir eğitim mevcuttur.

TensorFlow istekli modu

TensorFlow istekli mod arka ucu, her Tensor işlemini karşılaşıldığında bir GPU'ya veya CPU'ya göndermek için TensorFlow C API'sinden yararlanır. Daha sonra bu işlemin sonucu alınır ve bir sonraki işleme aktarılır.

Bu işlem bazında gönderimin anlaşılması kolaydır ve kodunuz içinde açık bir yapılandırma gerektirmez. Ancak çoğu durumda, birçok küçük işlemin gönderilmesinden kaynaklanan ek yük ve işlem grafikleri mevcut olduğunda oluşabilecek işlem füzyonu ve optimizasyon eksikliği nedeniyle optimum performansla sonuçlanmaz. Son olarak TensorFlow istekli modu TPU'larla uyumlu değildir ve yalnızca CPU'lar ve GPU'larla kullanılabilir.

X10 (XLA tabanlı izleme)

X10, çoğu durumda operasyon bazında gönderime göre performansı önemli ölçüde artırmak için tembel tensör izlemeyi ve XLA optimizasyon derleyicisini kullanan TensorFlow arka ucunun Swift'in adıdır. Ek olarak, makine öğrenimi modellerinde bulunan hesaplama türleri için özel olarak optimize edilmiş hızlandırıcılar olan TPU'lar için uyumluluk sağlar.

Tensor hesaplamaları için X10'un kullanımı varsayılan değildir, dolayısıyla bu arka ucu etkinleştirmeniz gerekir. Bu, bir Tensor bir XLA cihazına yerleştirildiğini belirterek yapılır:

let tensor1 = Tensor<Float>([0.0, 1.0, 2.0], on: Device.defaultXLA)
let tensor2 = Tensor<Float>([1.5, 2.5, 3.5], on: Device.defaultXLA)

Bu noktadan sonra bir hesaplamayı açıklamak, TensorFlow istekli modundakiyle tamamen aynıdır:

let tensor3 = tensor1 + tensor2

Bir Tensor oluştururken ne tür bir hızlandırıcının kullanılacağı ve hatta birkaç tane mevcutsa hangisinin kullanılacağı gibi daha fazla ayrıntı sağlanabilir. Örneğin, aşağıdakileri kullanarak ikinci TPU cihazında (programın çalıştığı ana bilgisayar tarafından görülebildiği varsayılarak) bir Tensor oluşturulabilir:

let tpuTensor = Tensor<Float>([0.0, 1.0, 2.0], on: Device(kind: .TPU, ordinal: 1, backend: .XLA))

Tensor cihazlar arasında örtülü hareketi yapılmaz, dolayısıyla farklı cihazlardaki iki Tensor bir işlemde birlikte kullanılırsa çalışma zamanı hatası meydana gelir. Bir Tensor içeriğini yeni bir cihaza manuel olarak kopyalamak için Tensor(copying:to:) başlatıcısını kullanabilirsiniz. Modeller ve optimize ediciler gibi, içinde Tensor bulunan bazı büyük ölçekli yapılar, tüm iç Tensor tek adımda yeni bir cihaza taşımak için yardımcı işlevlere sahiptir.

TensorFlow istekli modunun aksine, X10 arka ucunu kullanan işlemler, karşılaşıldığında ayrı ayrı gönderilmez. Bunun yerine, bir hızlandırıcıya gönderme yalnızca hesaplanan değerlerin ana bilgisayara geri okunmasıyla veya açık bir bariyer yerleştirilmesiyle tetiklenir. Bunun çalışma şekli, çalışma zamanının ana bilgisayara okunan değerden (veya manuel bariyerden önceki son hesaplamadan) başlaması ve bu değerle sonuçlanan hesaplamaların grafiğini izlemesidir.

Bu izlenen grafik daha sonra XLA HLO ara gösterimine dönüştürülür ve optimize edilmek ve hızlandırıcıda yürütülmek üzere derlenmek üzere XLA derleyicisine iletilir. Buradan hesaplamanın tamamı hızlandırıcıya gönderilir ve nihai sonuç elde edilir.

Hesaplama zaman alıcı bir işlemdir, bu nedenle X10 en iyi şekilde, bir grafik aracılığıyla ifade edilen ve birçok kez gerçekleştirilen büyük ölçüde paralel hesaplamalarda kullanılır. Hash değerleri ve önbelleğe alma, aynı grafiklerin her benzersiz konfigürasyon için yalnızca bir kez derleneceği şekilde kullanılır.

Makine öğrenimi modelleri için eğitim süreci genellikle modelin aynı dizi hesaplamaya tekrar tekrar tabi tutulduğu bir döngü içerir. Bu geçişlerin her birinin, içinde tekrarlanan birimler bulunan uzun bir grafik yerine, aynı izin tekrarı olarak görülmesini isteyeceksiniz. Bu, kodunuzdaki izlemenin bitmesini istediğiniz konumlara LazyTensorBarrier() işlevine manuel olarak bir çağrı eklenmesiyle etkinleştirilir.

X10'da karma hassasiyetli destek

X10 aracılığıyla karma hassasiyetle eğitim desteklenir ve bunun kontrol edilmesi için hem düşük seviyeli hem de yüksek seviyeli API sağlanır. Düşük seviyeli API iki hesaplanmış özellik sunar: tam ve azaltılmış hassasiyet arasında dönüşüm sağlayan toReducedPrecision ve toFullPrecision ile hassasiyeti sorgulamak için isReducedPrecision . Tensor yanı sıra modeller ve optimize ediciler bu API kullanılarak tam ve azaltılmış hassasiyet arasında dönüştürülebilir.

Azaltılmış duyarlılığa dönüştürmenin Tensor mantıksal türünü değiştirmediğini unutmayın. t bir Tensor<Float> ise, t.toReducedPrecision aynı zamanda azaltılmış duyarlıklı temel temsile sahip bir Tensor<Float> olur.

Cihazlarda olduğu gibi, farklı hassasiyetteki tensörler arasındaki işlemlere izin verilmez. Bu, kullanıcı tarafından tespit edilmesi zor olan 32 bitlik kayan noktalara sessiz ve istenmeyen terfiyi önler.