считайте файл в пути к классу

В вашей функции Mode, поскольку вы в основном вызываете функции-оболочки, вы не увидите такого большого улучшения по сравнению с базой R. На самом деле, просто написав точный базовый перевод R, мы имеем:

baseMode <- function(x, narm = FALSE) {
    if (narm) x <- x[!is.na(x)]
    ux <- unique(x)
    ux[which.max(table(match(x, ux)))]
}

И для сравнительного анализа имеем:

set.seed(1234)
s <- sample(1e5, replace = TRUE)

library(microbenchmark)
microbenchmark(Mode(s), baseMode(s), times = 10, unit = "relative")
Unit: relative
       expr      min       lq     mean   median       uq      max neval
    Mode(s) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    10
baseMode(s) 1.490765 1.645367 1.571132 1.616061 1.637181 1.448306    10

Как правило, когда мы предпринимаем усилия по написанию собственного скомпилированного код, мы ожидали бы большие выгоды. Простое объединение этих и без того эффективных скомпилированных функций в Rcpp не сможет волшебным образом принести вам ожидаемые результаты. На самом деле, на больших примерах базовое решение быстрее. Заметьте:

set.seed(1234)
sBig <- sample(1e6, replace = TRUE)

system.time(Mode(sBig))
 user  system elapsed 
1.410   0.036   1.450 

system.time(baseMode(sBig))
 user  system elapsed 
0.915   0.025   0.943 

Чтобы ответить на ваш вопрос о написании функции более быстрого режима, мы можем использовать std::unordered_map, который очень похож на table под капотом (т.е. они обе являются хеш-таблицами в их сердце). Кроме того, поскольку вы возвращаете одно целое число, мы можем с уверенностью предположить, что мы можем заменить NumericVector на IntegerVector, а также то, что вам не нужно возвращать каждое значение , которое встречается чаще всего.

Алгоритм, приведенный ниже, можно изменить, чтобы он возвращал истинный режим , но я оставлю это в качестве упражнения (подсказка: вам потребуется std::vector вместе с выполнением какого-либо действия, когда it->second == myMax) , Нотабене вам также нужно добавить // [[Rcpp::plugins(cpp11)]] вверху вашего файла cpp для std::unordered_map и auto.

#include 
using namespace Rcpp;

// [[Rcpp::plugins(cpp11)]]
#include 

// [[Rcpp::export]]
int fastIntMode(IntegerVector x, bool narm = false) {
    if (narm) x = x[!is_na(x)];
    int myMax = 1;
    int myMode = 0;
    std::unordered_map modeMap;
    modeMap.reserve(x.size());

    for (std::size_t i = 0, len = x.size(); i < len; ++i) {
        auto it = modeMap.find(x[i]);

        if (it != modeMap.end()) {
            ++(it->second);
            if (it->second > myMax) {
                myMax = it->second;
                myMode = x[i];
            }
        } else {
            modeMap.insert({x[i], 1});
        }
    }

    return myMode;
}

И тесты:

microbenchmark(Mode(s), baseMode(s), fastIntMode(s), times = 15, unit = "relative")
Unit: relative
          expr      min       lq     mean   median       uq      max neval
       Mode(s) 6.428343 6.268131 6.622914 6.134388 6.881746  7.78522    15
   baseMode(s) 9.757491 9.404101 9.454857 9.169315 9.018938 10.16640    15
fastIntMode(s) 1.000000 1.000000 1.000000 1.000000 1.000000  1.00000    15

Теперь мы говорим ... примерно в 6 раз быстрее, чем оригинал, и в 9 раз быстрее, чем база. Все они возвращают одно и то же значение:

fastIntMode(s)
##[1] 85433

baseMode(s)
##[1] 85433

Mode(s)
##[1] 85433

И для нашего более крупного примера:

## base R returned in 0.943s
system.time(fastIntMode(s))
 user  system elapsed 
0.217   0.006   0.224

31
задан Greg J 9 April 2009 в 15:13
поделиться

2 ответа

Try getting Spring to inject it, assuming you're using Spring as a dependency-injection framework.

In your class, do something like this:

public void setSqlResource(Resource sqlResource) {
    this.sqlResource = sqlResource;
}

And then in your application context file, in the bean definition, just set a property:

<bean id="someBean" class="...">
    <property name="sqlResource" value="classpath:com/somecompany/sql/sql.txt" />
</bean>

And Spring should be clever enough to load up the file from the classpath and give it to your bean as a resource.

You could also look into PropertyPlaceholderConfigurer, and store all your SQL in property files and just inject each one separately where needed. There are lots of options.

34
ответ дан 27 November 2019 в 21:53
поделиться

Change . to / as the path separator and use getResourceAsStream:

reader = new BufferedReader(new InputStreamReader(
    getClass().getClassLoader().getResourceAsStream(
        "com/company/app/dao/sql/SqlQueryFile.sql")));

or

reader = new BufferedReader(new InputStreamReader(
    getClass().getResourceAsStream(
        "/com/company/app/dao/sql/SqlQueryFile.sql")));

Note the leading slash when using Class.getResourceAsStream() vs ClassLoader.getResourceAsStream. getSystemResourceAsStream uses the system classloader which isn't what you want.

I suspect that using slashes instead of dots would work for ClassPathResource too.

39
ответ дан 27 November 2019 в 21:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: