我正在比较Julia计算3D空间中两组点之间的欧氏距离与C中的等效实现所花费的时间。我非常惊讶地发现(对于这个特殊情况和我的特定实现)Julia比C快22%。当我在Julia版本中包含@fastmath
时,它甚至比C快83%。
这引出了我的问题:为什么?朱莉娅比我最初认为的更令人惊讶或我在做一些非常低效的事情。我把钱押在后者身上。
有关实施的一些细节:
Float64
的二维数组。double
的一维数组。sqrt
中的math.h
函数。关于汇编的一些细节:
-O3 -ffast-math
时序:
@fastmath
):90秒@fastmath
):20 s time
作为计时
$ time ./particleDistance.jl
(文件中有shebang)$ time ./particleDistance
particleDistance.jl
#!/usr/local/bin/julia
function distance!(x::Array{Float64, 2}, y::Array{Float64, 2}, r::Array{Float64, 2})
nx = size(x, 1)
ny = size(y, 1)
for k = 1:1000
for j = 1:ny
@fastmath for i = 1:nx
@inbounds dx = y[j, 1] - x[i, 1]
@inbounds dy = y[j, 2] - x[i, 2]
@inbounds dz = y[j, 3] - x[i, 3]
rSq = dx*dx + dy*dy + dz*dz
@inbounds r[i, j] = sqrt(rSq)
end
end
end
end
function main()
n = 4096
m = 4096
x = rand(n, 3)
y = rand(m, 3)
r = zeros(n, m)
distance!(x, y, r)
println("r[n, m] = $(r[n, m])")
end
main()
particleDistance.c
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
void distance(int n, int m, double* x, double* y, double* r)
{
int i, j, I, J;
double dx, dy, dz, rSq;
for (int k = 0; k < 1000; k++)
{
for (j = 0; j < m; j++)
{
J = 3*j;
for (i = 0; i < n; i++)
{
I = 3*i;
dx = y[J] - x[I];
dy = y[J+1] - x[I+1];
dz = y[J+2] - x[I+2];
rSq = dx*dx + dy*dy + dz*dz;
r[j*n+i] = sqrt(rSq);
}
}
}
}
int main()
{
int i;
int n = 4096;
int m = 4096;
double *x, *y, *r;
size_t xbytes = 3*n*sizeof(double);
size_t ybytes = 3*m*sizeof(double);
x = (double*) malloc(xbytes);
y = (double*) malloc(ybytes);
r = (double*) malloc(xbytes*ybytes/9);
for (i = 0; i < 3*n; i++)
{
x[i] = (double) rand()/RAND_MAX*2.0-1.0;
}
for (i = 0; i < 3*m; i++)
{
y[i] = (double) rand()/RAND_MAX*2.0-1.0;
}
distance(n, m, x, y, r);
printf("r[n*m-1] = %f\n", r[n*m-1]);
free(x);
free(y);
free(r);
return 0;
}
生成文件
all: particleDistance.c
gcc -o particleDistance particleDistance.c -O3 -ffast-math -lm
答案 0 :(得分:0)
也许它应该是一个评论,但关键是朱莉娅确实非常优化。在Julia网页中,你可以看到它在某些情况下可以击败C(曼德尔)。
我看到你在编译中使用了-ffast-math。但是,也许你可以在你的代码中做一些优化(虽然现在的编译器非常聪明,这可能无法解决问题)。
可能还有其他一些东西,但是Julia已经通过实时编译进行了优化,因此所有不变且预先知道的东西都会被用来支持它。我没有后悔地试过朱莉娅。
答案 1 :(得分:0)
您在C中的指数计算相当缓慢
尝试类似下面的内容(我没有编译它,它可能仍然有错误,只是想象一下这个想法):
+---------------------+-----------+-----------+--------------+---------------------+----------------------+----------------------+
| Processing_Instance | Review_Id | gmpi | Memberid | Review_Date | attestation_fax_date | review_detail_status |
+---------------------+-----------+-----------+--------------+---------------------+----------------------+----------------------+
| 23760 | 11359973 | 650775278 | 300601690600 | 2017-03-30 00:00:00 | 2017-03-27 00:00:00 | Confirmed |
| 23760 | 11359973 | 650775278 | 300601690600 | 2017-03-30 00:00:00 | 2017-03-27 00:00:00 | Confirmed |
+---------------------+-----------+-----------+--------------+---------------------+----------------------+----------------------+
或者你可以尝试,它可能会更快一点(一个增量而不是3)
void distance(int n, int m, double* x, double* y, double* r)
{
int i, j;
double dx, dy, dz, rSq;
double* X, *Y, *R;
for (int k = 0; k < 1000; k++)
{
R = r;
Y = y;
for (j = 0; j < m; j++)
{
X = x;
for (i = 0; i < n; i++)
{
dx = Y[0] - *X++;
dy = Y[1] - *X++;
dz = Y[2] - *X++;
rSq = dx*dx + dy*dy + dz*dz;
*R++ = sqrt(rSq);
}
Y += 3;
}
}
}
Y [x]与*(Y + x)相同。
祝你好运