Поможет ли матрица разреженных строк в скорости вычислений этого кода? - PullRequest
0 голосов
/ 15 мая 2018

У меня есть два больших массива numpy с целочисленными записями, чьи записи в основном равны 0.В качестве иллюстрации предположим, что

    arr_one = np.array([[[1, 0, 0, 0, 0, 4], [3, 0, 0, 0, 0, 5],[3, 3, 0, 0, 0, 4]], 
                        [[2, 0, 0, 0, 0, 3], [2, 0, 0, 0, 0, 2],[2, 3, 0, 0, 0, 2]]])

    arr_two = np.array([[[3, 0, 0, 0, 0, 7], [4, 0, 0, 0, 0, 7],[5, 4, 0, 0, 0, 6]], 
                        [[3, 0, 0, 0, 0, 5], [6, 0, 0, 0, 0, 4],[5, 5, 0, 0, 0, 4]]])

У меня есть еще один массив, который содержит в основном ненулевые записи:

arr_main = np.array([[[1, 2, 4],[3, 2, 1],[3, 4, 5]], 
                     [[3, 4, 4],[3, 3, 3],[4, 4, 5]], 
                     [[4, 5, 4],[4, 6, 4],[3, 1, 6]]])

Эти цифры приведены только для иллюстраций, и с чем я имею деломассивы большего размера, в основном с нулями в качестве записей для arr_one и arr_two.Теперь мне нужно установить элементы arr_main в 0, основываясь на записях в arr_one.Процесс довольно запутанный, и мне нужно использовать несколько циклов for.Поскольку циклы в Python медленные, я написал код C и weaved в своем коде Python.Ниже описан код C:

        code = """
        #pragma omp parallel shared(arr_main, arr_one, arr_two, n1, n2) default(none)
        {
        int row_t, column_p, row, col;
        #pragma omp for reduction(+:fl)
        for (int i=0; i< n1; i++) {
            for (int j=0; j < n2; j++){
                for (row_t = arr_one(0,i,j); row_t < arr_two(0,i,j); row_t++){
                    row = row_t % 3;
                    for (column_p = arr_one(1,i,j); column_p < arr_two(1,i,j); column_p++){
                        col = (column_p - 1) % 3;
                        arr_main(row, col, i) = 0;
                    }
                }
            }
        }
        }
        """
        arr_main = np.ascontiguousarray(arr_main)
        arr_one = np.ascontiguousarray(arr_one)
        arr_two = np.ascontiguousarray(arr_two)
        n1 = 3
        n2 = 6
        try:
            if os.uname()[0] == 'Darwin':
                extra_compile_args = extra_link_args = ['-O3']
            else:
                extra_compile_args = extra_link_args = ['-O3 -fopenmp']
            get_flux = scipy.weave.inline(code, ['arr_main', 'arr_one', 'arr_two',  'n1', 'n2'], type_converters=scipy.weave.converters.blitz, compiler='gcc', extra_compile_args=extra_compile_args, extra_link_args=extra_link_args, headers=['<omp.h>','<cmath>'], libraries=['m'], verbose=2)
        except:
            get_flux = scipy.weave.inline(code, ['arr_main', 'arr_one', 'arr_two',  'n1', 'n2'], type_converters=scipy.weave.converters.blitz, compiler='gcc', extra_compile_args=['-O3'], extra_link_args=['-O3'], headers=['<cmath>'], libraries=['m'], verbose=2)

Поскольку мои настоящие массивы очень велики, а поскольку arr_one и arr_two редки, есть ли способ использовать scipy.sparse для созданияэто вычисление более эффективно и быстрее?

Обновление

Поскольку я зацикливаюсь даже на элементах, которые равны нулю и по существу могут быть отброшены, я создаю разреженную матрицу для arr_one чтобы получить индекс ненулевых элементов как:

arr_non_zero_first = csc_matrix(arr_one[0]).nonzero()
arr_non_zero_second = csc_matrix(arr_one[1]).nonzero()

Я не уверен, как включить это в этот weave сейчас, просто чтобы уменьшить количество циклов.

...