据我所知,在 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 不提供的两种不同的执行方式。
最佳答案
即使使用C语言的for循环,也比R语言的第一种方式快。 所以你不必担心 c 语言中的 for-loop 变慢。 查看下面的结果。
C 语言 for 循环: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;
}
关于c - 将操作应用于 C 中的整个内存块,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55047914/