Kıyaslama (BLAS kullanarak python vs. c++) ve (numpy)

| | | | | | | | | | | | | | | | | | | | | | | | | | |

BLAS ve LAPACK lineer cebir işlevlerini kapsamlı bir şekilde kullanan bir program yazmak istiyorum. Performans bir sorun olduğu için biraz kıyaslama yaptım ve bu yaklaşımın meşru olup olmadığını bilmek istiyorum.

Tabii ki üç yarışmacım var ve performanslarını basit bir matris matrisiyle test etmek istiyorum. çarpma işlemi. Yarışmacılar:

  1. Numpy, yalnızca dot işlevselliğinden yararlanıyor.
  2. Python, paylaşılan bir nesne aracılığıyla BLAS işlevlerini çağırıyor.
  3. C++, paylaşılan bir nesne aracılığıyla BLAS işlevlerini çağırıyor.

Senaryo

Farklı boyutlar için bir matris-matris çarpımı uyguladım ben. i, 5'lik artışlarla 5'ten 500'e kadar çalışır ve m1 ve m2 matrisleri şu şekilde ayarlanır:

m1 = numpy.random.rand(i,i).astype(numpy.float32) m2 = numpy.random.rand(i,i).astype(numpy.float32) 

1. Numpy

Kullanılan kod şöyle görünür:

tNumpy = timeit.Timer("numpy.dot(m1, m2)", "import numpy; from __main__ import m1 , m2") rNumpy.append((i, tNumpy.repeat(20, 1))) 

2. Python, paylaşılan bir nesne aracılığıyla BLAS'ı çağırma

İşlev ile

_blaslib = ctypes.cdll.LoadLibrary("libblas.so") def Mul(m1, m2, i , r): no_trans = c_char("n") n = c_int(i) bir = c_float(1.0) sıfır = c_float(0.0) _blaslib.sgemm_(byref(no_trans), byref(no_trans), byref(n), byref (n), byref(n), byref(one), m1.ctypes.data_as(ctypes.c_void_p), byref(n), m2.ctypes.data_as(ctypes.c_void_p), byref(n), byref(zero) , r.ctypes.data_as(ctypes.c_void_p), byref(n)) 

test kodu şöyle görünür:

r = numpy.zeros ((i,i), numpy.float32) tBlas = timeit.Timer("Mul(m1, m2, i, r)", "import numpy; __main__ import i, m1, m2, r, Mul") rBlas. append((i, tBlas.repeat(20, 1))) 

3. c++, paylaşılan bir nesne aracılığıyla BLAS'ı çağırma

Şimdi c++ kodu doğal olarak biraz daha uzun, bu yüzden bilgiyi minimuma indiriyorum.
İşlevi

void* tutamaç = dlopen("libblas.so", RTLD_LAZY); void* İşlev = dlsym(işleç, "sgemm_"); 

Saati şu şekilde gettimeofday ile ölçüyorum:

gettimeofday(&start, NULL); f(&no_trans, &no_trans, &dim, &dim, &dim, &one, A, &dim, B, &dim, &zero, Return, &dim); gettimeofday(&end, NULL); dTimes[j] = CalcTime(başlangıç, bitiş); 

burada j 20 kez çalışan bir döngüdür. Geçen süreyi

double CalcTime(timeval start, timeval end) { double factor = 1000000; dönüş (((double)end.tv_sec) * faktör + ((double)end.tv_usec) - (((double)start.tv_sec) * faktör + ((double)start.tv_usec))) / faktör; } 

Sonuçlar

Sonuç aşağıdaki grafikte gösterilmiştir:

resim açıklamasını buraya girin

Sorular

  1. Yaklaşımımın adil olduğunu mu düşünüyorsunuz, yoksa yapabileceğim bazı gereksiz masraflar var mı? kaçının?
  2. Sonucun c++ ve python yaklaşımı arasında bu kadar büyük bir farklılık göstermesini bekler miydiniz? Her ikisi de hesaplamaları için paylaşılan nesneleri kullanıyor.
  3. Programım için python kullanmayı tercih ettiğim için, BLAS veya LAPACK rutinlerini çağırırken performansı artırmak için ne yapabilirim?

İndirin

Karşılaştırmanın tamamı buradan indirilebilir. (JF Sebastian bu bağlantıyı mümkün kıldı^^)