2015-04-18 20 views
5

Monte Carlo sim'in sonuçlarını göstermesi gereken bir Rails uygulamasına sahibim ve Ruby ilk defa ihtiyaçlar için yeterince hızlı değil. Böylece, simülasyonumu C'ye yeniden yazıp yazmayacağımı görmek için bu işe karışmaya başladım ve bu sonuçları Ruby'de kullanıyorum ve biraz googling Ruby'de kolayca daha hızlı C kodu yazmak için RubyInline gemini açtı. Basit şeyler yapmak harika çalışıyor, örneğin, bazı temel işlevleri hem Yakut ve C ile yazılmış: Hemen hemen sadece rastgele sayılar üreten ve dayansın eşyalarını ekleyerek beriRubyInline gemini kullanarak C yapıları oluşturma

class FasterFunctions 
    inline do |builder| 
    builder.c ' 
    double rand_sum(int trials) 
    { 
     double sum = 0.0; 
     for (int i = 0; i<trials; i++) 
     { 
     sum += (double)rand()/(double)RAND_MAX; 
     } 
     return sum; 
    }' 

    builder.c ' 
    long loop_sum(long trials) 
    { 
     long sum = 0; 
     for (long i = 0; i<trials; i++) 
     { 
     sum+=i; 
     } 
     return sum; 
    }' 
    end 
end 

#the C version is 4 orders of magnitude faster 
trials = 1_000_000 
ruby_sum = 0 
trials.times {|i| ruby_sum += i} 
c_sum = FasterRand.new.loop_sum(trials) 

# the C version is 1 order of magnitude faster 
ruby_sum = 0.0 
trials.times {ruby_sum += rand} 
c_sum = FasterRand.new.rand_sum(trials) 

Yani, büyük, kesinlikle benim sim hızlandırmak gerektiğini bu sonuçlarda. Ne yazık ki, bunun gibi temel şeylerin ötesinde, programımı nasıl yazacağımı anlayamıyorum. Durum değişkenleri olarak hareket etmek için etraftaki bazı yapıları geçmem gerekiyor, bu yüzden işin ilk sırası bir C yapısının nasıl oluşturulacağını bulmaktır. the documentation'un okunması oldukça basit gibi gözüküyor.

accessor(method, type, member = method)

Adds a reader and writer for a C struct member wrapped via Data_Wrap_Struct. method is the ruby name to give the accessor, type is the C type. Unless the C member name is overridden with member, the method name is used as the struct member.

builder.struct_name = 'MyStruct' 
builder.accessor :title,  'char *' 
builder.accessor :stream_index, 'int', :index 

belgelerine benim için tamamen net değil, ama ben bunu erişmek için aşağıdaki gibi pek eskisi gibi bir sınıfta koyup bir şeyler yapacağıma varsayalım: Maalesef

class MyStructClass 
    inline do |builder| 
    builder.struct_name = 'MyStruct' 
    builder.accessor :title, 'char *' 
    builder.accessor :stream_index, 'int', :index 
    end 
end 

#possible this 
struct = MyStructClass.new.MyStruct 
struct.title = 'A Title' 

#or maybe 
struct = MyStructClass.new 
struct.title = 'A Title' 

Ben bile alamayan o kadar

*/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3: error: use of undeclared identifier 'MyStruct' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13: error: use of undeclared identifier 'pointer' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35: error: use of undeclared identifier 'pointer' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:25: error: use of undeclared identifier 'MyStruct' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:3: error: expected expression Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' return (rb_str_new2(pointer->title)); ^ */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:786:27: note: expanded from macro 'rb_str_new_cstr' (__builtin_constant_p(str)) ? \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:14: note: expanded from macro 'rb_str_new_cstr' rb_str_new((str), (long)strlen(str)) : \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:787:33: note: expanded from macro 'rb_str_new_cstr' rb_str_new((str), (long)strlen(str)) : \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:23: error: use of undeclared identifier 'pointer' */.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/intern.h:788:18: note: expanded from macro 'rb_str_new_cstr' rb_str_new_cstr(str); \ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:460:10: error: returning 'void' from a function with incompatible result type 'VALUE' (aka 'unsigned long') return (rb_str_new2(pointer->title)); ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:3: error: use of undeclared identifier 'MyStruct' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:478:13: error: use of undeclared identifier 'pointer' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:35: error: use of undeclared identifier 'pointer' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:25: error: use of undeclared identifier 'MyStruct' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:15: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:480:3: error: expected expression Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:20: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:482:3: error: use of undeclared identifier 'pointer' pointer->title = StringValuePtr(value); ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:3: error: use of undeclared identifier 'MyStruct' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:456:13: error: use of undeclared identifier 'pointer' MyStruct *pointer; ^ */.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/RubyInline-3.12.4/lib/inline.rb:458:35: error: use of undeclared identifier 'pointer' Data_Get_Struct(self, MyStruct, pointer); ^ /.rbenv/versions/2.1.2/include/ruby-2.1.0/ruby/ruby.h:1038:6: note: expanded from macro 'Data_Get_Struct' (sval) = (type)DATA_PTR(obj);\ ^fatal error: too many errors emitted, stopping now [-ferror-limit=]

sadece ben ilk başta özetlenen basit kullanım durumunda olan fırsatları Ben googling bir demet yaptık ama hemen hemen her örneği buldum. o tükürmek ilk hata MyStruct bildirilmemiş olduğunu, bu yüzden şöyle, erişimci yöntemlere önce yapı tanımını ekleyerek çalıştı:

builder.c ' 
    typedef struct 
    { 
    char *title; 
    int index; 
    } MyStruct; 
' 

şey yapmaz O ve dokümantasyon açıkça görünmektedir c metodu sadece yapıları değil, işlevleri bildirmek içindir. Bundan sonra ne denemem gerektiğinden emin değilim, başkalarının bununla ilgili deneyimi var mı?

cevap

3

RubyInline, temellerden daha karmaşık bir şey yapıyorsanız Ruby uzantıları yazmanın yolunu bildiğinizi varsayar.

Sen çalışırken yapı kendini tanımlamak için ihtiyacını yapmak , ancak (yöntemleri tanımlamak için olan) yerine c method daha prefix method kullanmalıdır. Ayrıca, sınıf için tahsis yöntemini tanımlamanız gerekir. ile allocate adlı bir fonksiyon ekleyerek RubyInline'ın ayırma işlevi olarak tanımlayacağını ve kullanacağını (bu, belgelenmemiş gibi görünüyor, kaynağa bakarak buldum) ekleyerek bunu yapabilirsiniz.

Hepsini bir araya getirmek, böyle bir şeye benziyor. Evinizde Rehberde .ruby_inline altında bakarsak

class Foo 
    inline do |builder| 

    # First define the struct that will be wrapped in the 
    # class. 
    builder.prefix <<-DEFINE_STRUCT 
     typedef struct { 
     char* bar; 
     } MyStruct; 
    DEFINE_STRUCT 

    # Next define the allocation function that will 
    # allocate and wrap a MyStruct struct when creating a 
    # new Foo object. You might want to initialize the values 
    # to avoid possible segfaults. 
    builder.c_singleton <<-ALLOCATE 
     VALUE allocate() { 
     MyStruct* pointer = ALLOC(MyStruct); 
     return Data_Wrap_Struct(self, NULL, free, pointer); 
     } 
    ALLOCATE 

    # Finally we can use the struct_name and accessor methods. 
    builder.struct_name = 'MyStruct' 
    builder.accessor 'bar', 'char *' 
    end 

end 

Not oluşturulan C kodunu görebilirsiniz.

İlgili konular