W niektórych przypadkach podczas kompilacji użytkownik wie, jaka konkretna część danych algorytmu wygląda i może chcieć przekazać tę informację do kompilatora. To pytanie dotyczy tego, jak najlepiej to osiągnąć.Optymalizowanie danych zależnych od czasu kompilacji
Tytułem przykładu, rozważmy następujący przykład rzadkiej mnożenia macierzy, w których matryca jest stała i znana w czasie kompilacji:
matrix = [ 0, 210, 0, 248, 137]
[ 0, 0, 0, 0, 239]
[ 0, 0, 0, 0, 0]
[116, 112, 0, 0, 7]
[ 0, 0, 0, 0, 165]
W takim przypadku, w pełni branchless realizacja może zostać zapisane realizacji wektor mnożenie macierzy do dowolnego wektora wejściowego:
#include <stdio.h>
#define ARRAY_SIZE 8
static const int matrix[ARRAY_SIZE] = {210, 248, 137, 239, 116, 112, 7, 165};
static const int input_indices[ARRAY_SIZE] = {1, 3, 4, 4, 0, 1, 4, 4};
static const int output_indices[ARRAY_SIZE] = {0, 0, 0, 1, 3, 3, 3, 4};
static void matrix_multiply(int *input_array, int *output_array)
{
for (int i=0; i<ARRAY_SIZE; ++i){
output_array[output_indices[i]] += (
matrix[i] * input_array[input_indices[i]]);
}
}
int main()
{
int test_input[5] = {36, 220, 212, 122, 39};
int output[5] = {0};
matrix_multiply(test_input, output);
for (int i=0; i<5; ++i){
printf("%d\n", output[i]);
}
}
drukowany poprawny wynik dla macierzy-wektor (81799, 9321, 0, 29089, 6435
).
Można przewidzieć dalsze optymalizacje, które opierają się na specyficznej dla danych wiedzy na temat obszaru pamięci odniesienia.
Oczywiście, jest to podejście, z którego można korzystać, ale staje się ono nieporęczne, gdy rozmiar danych staje się duży (powiedzmy ~ 100 MB w moim przypadku), a także w każdej rzeczywistej sytuacji zależałoby od meta-programowania generować powiązaną wiedzę zależną od danych.
Czy ogólna strategia pieczenia w wiedzy dotyczącej danych ma przebieg w zakresie optymalizacji? Jeśli tak, jakie jest najlepsze podejście do tego?
W podanym przykładzie, na jednym poziomie, całość nie zostanie zredukowana do wiedzy o ARRAY_SIZE
z tablicami ustawionymi w czasie wykonywania. To prowadzi mnie do myślenia, że podejście jest ograniczone (i tak naprawdę jest to problem struktur danych), ale jestem bardzo zainteresowany, aby wiedzieć, czy ogólne podejście danych pochodzących z optymalizacji kompilacji jest przydatne w każdej sytuacji.
Myślę, że to zbyt ogólne pytanie. Jeśli potrzebujesz szybkiej macierzy rzadkiej, wybierz jedną z poniższych: https://en.wikipedia.org/wiki/List_of_numerical_libraries lub przeczytaj ich kod, aby zrozumieć, w jaki sposób je implementują. Jeśli chcesz przeprowadzić optymalizację w oparciu o algorytm, który wybierzesz, użyjesz swojego kompilatora do swojego kodu z oprzyrządowaniem, który uruchomi go za pomocą wspólnego wejścia, a następnie przebuduje i zoptymalizuje kod zgodnie z poprzednim uruchomieniem, co najmniej gcc/clang może to zrobić. – fghj
@ user1034749 Tyle, że ogólna, rzadka biblioteka nigdy nie może być tak szybka jak implementacja z dostrajaniem danych, co jest moim celem. Myślę o poziomie przekraczającym nawet automatycznie dostrojone biblioteki (np. FFTW, ATLAS). Nie jestem świadomy żadnej biblioteki, która próbuje użyć struktury w konkretnej instancji danych do optymalizacji, ale mogę się mylić. –
Nie jestem pewien, czy w pełni rozumiem twoje pytanie. Dlaczego programowanie meta? Potrzebujesz wstępnej obróbki. Chcesz wiedzieć, jak działa wstępne przetwarzanie i kiedy należy go używać? Z powodu mojego słabego angielskiego nie rozumiem również, że "pieczenie w danych, które mają konkretną wiedzę ma przebieg w zakresie optymalizacji?", Czy możesz przeformułować to zdanie? Dzięki! –