Применить операцию ко всему блоку памяти в C - PullRequest
1 голос
/ 07 марта 2019

Как я знаю на языке C, чтобы умножить массив на скаляр, вы должны перебирать каждый элемент, используя цикл for. И, как я знаю, исходный код для программной среды R написан в основном на C. И оттуда, когда у меня есть большая матрица в R, такая как mat = matrix(5, nrow = 1100, ncol = 1100), а затем умножить ее на константу и измерить время этой операции, просто вот так:

t_start = Sys.time()
mat = mat *5 
print(Sys.time()-t_start)

Выход:

Time difference of 0.005984068 secs

Но, делая то же самое с помощью циклов for, это занимает слишком много времени:

t_start = Sys.time()
for(i in 1:1100)
{
  for(j in 1:1100)
  {
    mat[i,j] = mat[i,j] * 5
  }
}
print(Sys.time()-t_start)

выход:

Time difference of 0.1437349 secs

Второй способ примерно в 24 раза медленнее, и теперь я предполагаю, что за кулисами первый способ также был сделан с помощью циклов for, если так, то почему разница во времени слишком большая?!

Мне интересно, есть ли лучший способ применить операцию ко всему блоку памяти в C без итерации по каждому элементу с использованием циклов. Я хотел бы получить некоторые ответы с точки зрения языка C, поскольку в настоящее время я работаю с C. И эти фрагменты R-кода были просто для демонстрации двух разных способов сделать это, которые R предоставляет, а C - нет.

1 Ответ

1 голос
/ 08 марта 2019

Даже используйте язык C для цикла, это быстрее, чем первый способ В языке R. так что вам не нужно беспокоиться о цикле for медленнее в языке c. Смотрите результаты ниже.

C язык для цикла: 0.00093478 сек

gcc -otest test.c -g -Wall -O2
./test
Time difference of 0.00093478 secs

Первый путь На языке R: 0.004915237 сек

./Rscript first.R 
Time difference of 0.004915237 secs

код test.c:

#include <stdio.h>
#include <time.h>
#include <stdlib.h>

typedef struct matrix {
    int nrow;
    int ncol;
    int *buf;
    int *(array[]);
} matrix;

double sys_time()
{
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec + ts.tv_nsec / 1000000000.0;
}

void test(matrix *mat)
{
    int i, j;
    double t_start, t_end;

    t_start = sys_time();
    for(i = 0; i < mat->nrow; i++) {
        for(j = 0; j < mat->ncol; j++) {
            mat->array[i][j] *= 5;
        }
    }
    t_end = sys_time();
    printf("Time difference of %g secs\n", t_end - t_start);
}

matrix *create_matrix(int val, int nrow, int ncol)
{
    matrix *mat;
    int *buf;
    int i, j;

    mat = (matrix *)malloc(sizeof(*mat) + nrow * sizeof(int *));
    buf = (int *)malloc(sizeof(int) * nrow * ncol);
    mat->buf = buf;
    mat->nrow = nrow;
    mat->ncol = ncol;
    for(i = 0; i < nrow; i++) {
        for(j = 0; j < ncol; j++)
            buf[j] = val;
        mat->array[i] = buf;
        buf += ncol;
    }
    return mat;
}

void destroy_matrix(matrix *mat)
{
    free(mat->buf);
    free(mat);
}

int main()
{
    matrix *mat;

    mat = create_matrix(5, 1100, 1100);
    test(mat);
    destroy_matrix(mat);

    return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...