Jun
16
2009
Here is a great, free econometrics tool-box, courtesy of James P. LeSage. It has an accompanying manual which can be downloaded here. Just make sure you add the library location to your Matlab search path (File > Set Path)!
Also on the site is a long (200 pages) book (?) on Spatial Econometrics, which you can get here. As well, he has another long (300 pages) book on The Theory and Practice of Spatial Econometrics. Grab it here.
And finally, also available is his book Applied Econometrics using MATLAB. 350 pages, and definitely worth a look!
no comments | tags: econometrics, matlab
Jun
16
2009
I decided to see what sort of speed-up I could get just doing a straight brute-force sort. First, I wanted a pure Ruby implementation. Next, I wanted a RubyInline version. Finally, I wanted to use RubyInline with Thrust. Here is the code I used.
Please NOTE: I understand that the appropriate choice of an algorithm is more important than ‘micro’ optimizations. I just thought it would be fun to check out.
# Ruby Sort Neighbors example
# Take N random (x,y) points
# For each point, sort the neighbors!
require 'rubygems'
require 'inline'
N = 1_000
class Point
attr_accessor :x, :y
def initialize(x, y)
@x = x
@y = y
end
def distance(other)
Math.sqrt((other.x - @x)**2 + (other.y - @y)**2)
end
end
def find_nearest_neighbors(point, neighbors)
return neighbors.sort { |a,b| point.distance(a) <=> point.distance(b) }
end
class NearestNeighbor
inline(:C) do |builder|
builder.add_compile_flags '-x c++', '-lstdc++', '-I/usr/local/include/boost-1_39/'
builder.include '<algorithm>'
builder.include '<vector>'
builder.include '<boost/bind.hpp>'
builder.include '<cmath>'
builder.prefix '
int distance(VALUE a, VALUE b, VALUE c) {
double a_x = NUM2DBL(rb_iv_get(a, "@x"));
double a_y = NUM2DBL(rb_iv_get(a, "@y"));
double b_x = NUM2DBL(rb_iv_get(b, "@x"));
double b_y = NUM2DBL(rb_iv_get(b, "@y"));
double c_x = NUM2DBL(rb_iv_get(c, "@x"));
double c_y = NUM2DBL(rb_iv_get(c, "@y"));
double b_dist = sqrt(pow(b_x-a_x, 2) + pow(b_y-a_y, 2));
double c_dist = sqrt(pow(c_x-a_x, 2) + pow(c_y-a_y, 2));
return (b_dist < c_dist);
}'
builder.c '
VALUE find_nearest_neighbors(VALUE point, VALUE neighbors) {
const VALUE *base = RARRAY(neighbors)->ptr;
std::vector<VALUE> sorted_neighbors(base, base + RARRAY(neighbors)->len);
std::sort(sorted_neighbors.begin(), sorted_neighbors.end(), boost::bind(&distance, point, _1, _2));
return rb_ary_new4(RARRAY(neighbors)->len, &sorted_neighbors.front());
}'
end
end
class NearestNeighborThrust
inline(:C) do |builder|
builder.add_compile_flags '-x c++', '-lstdc++', '-I/usr/local/cuda/include'
builder.include '<vector>'
builder.include '<cmath>'
builder.include '<thrust/sort.h>'
builder.prefix '
float distance(VALUE a, VALUE b) {
double a_x = NUM2DBL(rb_iv_get(a, "@x"));
double a_y = NUM2DBL(rb_iv_get(a, "@y"));
double b_x = NUM2DBL(rb_iv_get(b, "@x"));
double b_y = NUM2DBL(rb_iv_get(b, "@y"));
return sqrt(pow(b_x-a_x, 2) + pow(b_y-a_y, 2));
}'
builder.c '
VALUE find_nearest_neighbors(VALUE point, VALUE neighbors) {
VALUE *base = RARRAY(neighbors)->ptr;
const int length = RARRAY(neighbors)->len;
std::vector<double> keys(length);
for(int i = 0; i < length; i++)
keys[i] = distance(point, base[i]);
thrust::sort_by_key(&keys.front(), &keys.front()+length, base);
return rb_ary_new4(length, base);
}'
end
end
# initialize our points
points = []
N.times {
points << Point.new(rand, rand)
}
nearest_neighbors = []
start = Time.now
points.each_index { |i|
nearest_neighbors[i] = find_nearest_neighbors(points[i], points[0...i] + points[i+1..(N-1)])
}
finish = Time.now
puts "Ruby Time: #{finish-start}"
nearest_neighbors_inline = []
nn = NearestNeighbor.new()
start = Time.now
points.each_index { |i|
nearest_neighbors_inline[i] = nn.find_nearest_neighbors(points[i], points[0...i] + points[i+1..(N-1)])
}
finish = Time.now
puts "Inline Time: #{finish-start}"
nearest_neighbors_thrust = []
nn_thrust = NearestNeighborThrust.new()
start = Time.now
points.each_index { |i|
nearest_neighbors_thrust[i] = nn_thrust.find_nearest_neighbors(points[i], points[0...i] + points[i+1..(N-1)])
}
finish = Time.now
puts "Inline w/ Thrust: #{finish-start}"
Here are the results I got on my new MacBook 13″:
Ruby Time: 46.998292
Inline Time: 5.911666
Inline w/ Thrust: 0.726583
4 comments