Secara umum, algoritma yang bekerja lebih cepat pada GPU adalah algoritma di mana Anda melakukan jenis instruksi yang sama pada banyak titik data yang berbeda.
Contoh mudah untuk menggambarkan ini adalah dengan perkalian matriks.
Misalkan kita sedang melakukan perhitungan matriks
A × B = C
Algoritme CPU sederhana mungkin terlihat seperti ini
// dimulai dengan C = 0
for (int i = 0; i < C_Width; i++)
{
for (int j = 0; j < C_Height; j++)
{
for (int k = 0; k < A_Width; k++)
{
for (int l = 0; l < B_Height; l++)
{
C[j, i] += A[j, k] * B[l, i];
}
}
}
}
Kuncinya untuk dilihat di sini adalah ada banyak loop yang bersarang dan setiap langkah harus dijalankan satu demi satu.
Lihat diagram ini
Perhatikan bahwa perhitungan setiap elemen C tidak tergantung pada elemen lainnya. Jadi tidak masalah urutan urut apa yang dilakukan.
Jadi pada GPU, operasi ini bisa dilakukan bersamaan.
Kernel GPU untuk menghitung perkalian matriks akan terlihat seperti ini
__kernel void Multiply
(
__global float * A,
__global float * B,
__global float * C
)
{
const int x = get_global_id(0);
const int y = get_global_id(1);
for (int k = 0; k < A_Width; k++)
{
for (int l = 0; l < B_Height; l++)
{
C[x, y] += A[x, k] * B[l, y];
}
}
}
Kernel ini hanya memiliki dua inner untuk loop. Suatu program yang mengirimkan pekerjaan ini ke GPU akan memberitahu GPU untuk menjalankan kernel ini untuk setiap titik data dalam C. GPU akan melakukan masing-masing instruksi ini secara bersamaan di banyak utas. Sama seperti pepatah lama "Lebih murah oleh selusin" GPU dirancang untuk lebih cepat melakukan hal yang sama berkali-kali.
Namun ada beberapa algoritma yang akan memperlambat GPU. Beberapa tidak cocok untuk GPU.
Jika misalnya, ada dependensi data, yaitu: bayangkan perhitungan setiap elemen C tergantung pada elemen sebelumnya. Programmer harus meletakkan penghalang di kernel untuk menunggu setiap perhitungan sebelumnya selesai. Ini akan menjadi penurunan besar.
Juga, algoritma yang memiliki banyak logika percabangan yaitu:
__kernel Foo()
{
if (somecondition)
{
do something
}
else
{
do something completely different
}
}
cenderung berjalan lebih lambat pada GPU karena GPU tidak lagi melakukan hal yang sama di setiap utas.
Ini adalah penjelasan yang disederhanakan karena ada banyak faktor lain yang perlu dipertimbangkan. Misalnya, mengirim data antara CPU dan GPU juga memakan waktu. Kadang-kadang ada baiknya melakukan perhitungan pada GPU bahkan ketika itu lebih cepat pada CPU, hanya untuk menghindari waktu pengiriman tambahan (Dan sebaliknya).
Juga banyak CPU modern mendukung konkurensi sekarang juga dengan prosesor multicore hyperthreaded.
GPU juga tampaknya tidak begitu baik untuk rekursi, lihat di sini yang mungkin menjelaskan beberapa masalah dengan algoritma QR. Saya percaya bahwa seseorang memiliki beberapa dependensi data rekursif.