Skip to content

Commit

Permalink
More work
Browse files Browse the repository at this point in the history
  • Loading branch information
Kevin Smith committed Mar 9, 2011
1 parent ef8baf9 commit 6740249
Show file tree
Hide file tree
Showing 7 changed files with 164 additions and 5 deletions.
26 changes: 26 additions & 0 deletions c_src/pcuda_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ bool PCudaIntBuffer::sort() {
return pcuda_integer_sort(this->data);
}

bool PCudaIntBuffer::contains(ErlNifEnv *env, ERL_NIF_TERM rawTarget) {
long target;
if (enif_get_long(env, rawTarget, &target)) {
return pcuda_integer_binary_search(this->data, target);
}
else {
return false;
}
}

ERL_NIF_TERM PCudaIntBuffer::toErlTerms(ErlNifEnv *env) {
std::vector<long>::iterator iter;
ERL_NIF_TERM retval = enif_make_list(env, 0);
Expand All @@ -40,3 +50,19 @@ ERL_NIF_TERM PCudaIntBuffer::toErlTerms(ErlNifEnv *env) {
}
return retval;
}

void PCudaIntBuffer::clear() {
this->data->clear();
}

bool PCudaIntBuffer::copy(PCudaBuffer *src) {
if (src->type() == BUF_TYPE_INTEGER) {
PCudaIntBuffer *source = (PCudaIntBuffer *) src;
std::vector<long>::iterator iter;
for (iter = source->data->begin(); iter != source->data->end(); ++iter) {
this->data->push_back(*iter);
}
return true;
}
return false;
}
8 changes: 7 additions & 1 deletion c_src/pcuda_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ class PCudaBuffer {
virtual unsigned int size() = 0;
virtual PCudaBufferTypes type() = 0;
virtual bool sort() = 0;
virtual bool contains(ErlNifEnv *env, ERL_NIF_TERM rawTarget) = 0;
virtual void write(ErlNifEnv *env, ERL_NIF_TERM data) = 0;
virtual void clear() = 0;
virtual bool copy(PCudaBuffer *src) = 0;
virtual ERL_NIF_TERM toErlTerms(ErlNifEnv *env) = 0;
};

Expand All @@ -26,10 +29,13 @@ class PCudaIntBuffer : public PCudaBuffer {
virtual unsigned int size();
virtual PCudaBufferTypes type() { return BUF_TYPE_INTEGER; };
virtual bool sort();
virtual bool contains(ErlNifEnv *env, ERL_NIF_TERM rawTarget);
virtual ERL_NIF_TERM toErlTerms(ErlNifEnv *env);
virtual void write(ErlNifEnv *env, ERL_NIF_TERM data);
virtual void clear();
virtual bool copy(PCudaBuffer *src);

private:
protected:
std::vector<long> *data;
};
#endif
7 changes: 7 additions & 0 deletions c_src/pcuda_ops.cu
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,17 @@
#include <thrust/device_vector.h>
#include <thrust/copy.h>
#include <thrust/sort.h>
#include <thrust/functional.h>
#include <thrust/binary_search.h>

bool pcuda_integer_sort(std::vector<long> *data) {
thrust::device_vector<long> device = *data;
thrust::sort(device.begin(), device.end());
thrust::copy(device.begin(), device.end(), data->begin());
return true;
}

bool pcuda_integer_binary_search(std::vector<long> *data, long target) {
thrust::device_vector<long> device = *data;
return thrust::binary_search(device.begin(), device.end(), target, thrust::less<long>());
}
1 change: 1 addition & 0 deletions c_src/pcuda_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@
#include <vector>

bool pcuda_integer_sort(std::vector<long> *data);
bool pcuda_integer_binary_search(std::vector<long> *data, long target);

#endif
56 changes: 54 additions & 2 deletions c_src/pteracuda_nifs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,20 @@ extern "C" {
ERL_NIF_TERM pteracuda_nifs_write_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pteracuda_nifs_read_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pteracuda_nifs_sort_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pteracuda_nifs_clear_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pteracuda_nifs_buffer_contains(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pteracuda_nifs_copy_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]);

static ErlNifFunc pteracuda_nif_funcs[] = {
{"new_buffer", 0, pteracuda_nifs_new_buffer},
{"destroy_buffer", 1, pteracuda_nifs_destroy_buffer},
{"buffer_size", 1, pteracuda_nifs_buffer_size},
{"write_buffer", 2, pteracuda_nifs_write_buffer},
{"read_buffer", 1, pteracuda_nifs_read_buffer},
{"sort_buffer", 1, pteracuda_nifs_sort_buffer}
{"sort_buffer", 1, pteracuda_nifs_sort_buffer},
{"clear_buffer", 1, pteracuda_nifs_clear_buffer},
{"buffer_contains", 2, pteracuda_nifs_buffer_contains},
{"copy_buffer", 2, pteracuda_nifs_copy_buffer},
};
}

Expand All @@ -55,6 +61,8 @@ struct PCudaBufferRef {
CUcontext ctx;
};

static ERL_NIF_TERM ATOM_TRUE;
static ERL_NIF_TERM ATOM_FALSE;
static ERL_NIF_TERM ATOM_OK;
static ERL_NIF_TERM ATOM_ERROR;
static ERL_NIF_TERM ATOM_WRONG_TYPE;
Expand All @@ -64,6 +72,8 @@ ERL_NIF_INIT(pteracuda_nifs, pteracuda_nif_funcs, &pteracuda_on_load, NULL, NULL

static int pteracuda_on_load(ErlNifEnv *env, void **priv_data, ERL_NIF_TERM load_info) {
if (cuInit(0) == CUDA_SUCCESS) {
ATOM_TRUE = enif_make_atom(env, "true");
ATOM_FALSE = enif_make_atom(env, "false");
ATOM_OK = enif_make_atom(env, "ok");
ATOM_ERROR = enif_make_atom(env, "error");
ATOM_WRONG_TYPE = enif_make_atom(env, "wrong_type");
Expand Down Expand Up @@ -99,7 +109,6 @@ ERL_NIF_TERM pteracuda_nifs_destroy_buffer(ErlNifEnv *env, int argc, const ERL_N
}
delete ref->buffer;
cuCtxDestroy(ref->ctx);
//cudaThreadExit();
return ATOM_OK;
}

Expand Down Expand Up @@ -145,3 +154,46 @@ ERL_NIF_TERM pteracuda_nifs_read_buffer(ErlNifEnv *env, int argc, const ERL_NIF_
ERL_NIF_TERM data = ref->buffer->toErlTerms(env);
return enif_make_tuple2(env, ATOM_OK, data);
}

ERL_NIF_TERM pteracuda_nifs_clear_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
PCudaBufferRef *ref;
if (argc != 1 || !enif_get_resource(env, argv[0], pteracuda_buffer_resource, (void **) &ref)) {
return enif_make_badarg(env);
}
ref->buffer->clear();
return ATOM_OK;
}

ERL_NIF_TERM pteracuda_nifs_buffer_contains(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
PCudaBufferRef *ref;
if (argc !=2 || !enif_get_resource(env, argv[0], pteracuda_buffer_resource, (void **) &ref)) {
return enif_make_badarg(env);
}
if (ref->buffer->size() > 0) {
cuCtxSetCurrent(ref->ctx);
if (ref->buffer->contains(env, argv[1])) {
return ATOM_TRUE;
}
else {
return ATOM_FALSE;
}
}
else {
return ATOM_FALSE;
}
}

ERL_NIF_TERM pteracuda_nifs_copy_buffer(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
PCudaBufferRef *src, *dest;
if (argc !=2 || !enif_get_resource(env, argv[0], pteracuda_buffer_resource, (void **) &src) ||
!enif_get_resource(env, argv[1], pteracuda_buffer_resource, (void **) &dest)) {
return enif_make_badarg(env);
}

if (dest->buffer->copy(src->buffer)) {
return ATOM_OK;
}
else {
return ATOM_ERROR;
}
}
30 changes: 30 additions & 0 deletions src/pteracuda_bench.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
-module(pteracuda_bench).

-export([run/0]).

run() ->
{T1, T2, T3} = erlang:now(),
random:seed(T1, T2, T3),
F = fun(_, _) -> random:uniform(100) > 50 end,
N = lists:sort(F, lists:seq(1, 50000)),
Erlang = bench_pure_erlang(N, 10, []),
{ok, B} = pteracuda_nifs:new_buffer(),
Cuda = bench_cuda(B, N, 10, []),
pteracuda_nifs:destroy_buffer(B),
{lists:sum(Erlang) / length(Erlang), lists:sum(Cuda) / length(Cuda)}.

bench_pure_erlang(_N, 0, Accum) ->
Accum1 = lists:delete(lists:max(Accum), Accum),
lists:delete(lists:min(Accum1), Accum1);
bench_pure_erlang(N, Count, Accum) ->
{Time, _} = timer:tc(lists, sort, [N]),
bench_pure_erlang(N, Count - 1, [Time|Accum]).

bench_cuda(_Buf, _N, 0, Accum) ->
Accum1 = lists:delete(lists:max(Accum), Accum),
lists:delete(lists:min(Accum1), Accum1);
bench_cuda(Buf, N, Count, Accum) ->
pteracuda_nifs:write_buffer(Buf, N),
{Time, _} = timer:tc(pteracuda_nifs, sort_buffer, [Buf]),
pteracuda_nifs:clear_buffer(Buf),
bench_cuda(Buf, N, Count - 1, [Time|Accum]).
41 changes: 39 additions & 2 deletions src/pteracuda_nifs.erl
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,12 @@
buffer_size/1]).

-export([write_buffer/2,
read_buffer/1]).
read_buffer/1,
clear_buffer/1,
copy_buffer/2]).

-export([sort_buffer/1]).
-export([sort_buffer/1,
buffer_contains/2]).

new_buffer() ->
?MISSING_NIF.
Expand All @@ -39,6 +42,15 @@ write_buffer(_Buffer, _Data) ->
sort_buffer(_Buffer) ->
?MISSING_NIF.

clear_buffer(_Buffer) ->
?MISSING_NIF.

copy_buffer(_From, _To) ->
?MISSING_NIF.

buffer_contains(_Buffer, _Value) ->
?MISSING_NIF.

init() ->
PrivDir = case code:priv_dir(pteracuda) of
{error, bad_name} ->
Expand Down Expand Up @@ -70,4 +82,29 @@ create_write_sort_destroy_test() ->
{ok, [1,2,3,4,5]} = pteracuda_nifs:read_buffer(Buf),
ok = pteracuda_nifs:destroy_buffer(Buf).

create_write_clear_test() ->
{ok, Buf} = pteracuda_nifs:new_buffer(),
ok = pteracuda_nifs:write_buffer(Buf, [3,2,1,4,5]),
{ok, 5} = pteracuda_nifs:buffer_size(Buf),
pteracuda_nifs:clear_buffer(Buf),
{ok, 0} = pteracuda_nifs:buffer_size(Buf),
ok = pteracuda_nifs:destroy_buffer(Buf).

create_write_contains_test() ->
{ok, Buf} = pteracuda_nifs:new_buffer(),
N = lists:seq(1, 1000),
ok = pteracuda_nifs:write_buffer(Buf, N),
true = pteracuda_nifs:buffer_contains(Buf, 513),
false = pteracuda_nifs:buffer_contains(Buf, 1500),
ok = pteracuda_nifs:destroy_buffer(Buf).

create_copy_test() ->
{ok, Buf} = pteracuda_nifs:new_buffer(),
ok = pteracuda_nifs:write_buffer(Buf, lists:seq(1, 1000)),
{ok, Buf1} = pteracuda_nifs:new_buffer(),
ok = pteracuda_nifs:copy_buffer(Buf, Buf1),
{ok, 1000} = pteracuda_nifs:buffer_size(Buf1),
ok = pteracuda_nifs:destroy_buffer(Buf),
ok = pteracuda_nifs:destroy_buffer(Buf1).

-endif.

0 comments on commit 6740249

Please sign in to comment.