2018年6月26日火曜日

Could not find com.android.tools.lint:lint-gradle:26.1.2 備忘録

Android Studio Gradle 系のトラブルが多い。

Could not find com.android.tools.lint:lint-gradle:26.1.2.

とかでエラーが出た場合は、プロジェクトの build.gradle を修正する

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.1.3'
    }
}

allprojects {
    repositories {
        // google 先生が追加されますた
        google()
        jcenter()
    }
}

追記: jcenter と google の位置関係は、google を先にした方が良いようです。
gradle:3.1.3 と記述している箇所は、どんどんバージョンが上がります。

2018年6月9日土曜日

boost::compute テスト

ちょいと GPU 使ってみようかと思って OpenCL について調べました。macbook pro retina MID2012 が壊れて、GPU が Intel Iris しか搭載されてないものに買い替えたため、Cuda は選択肢に無くなったんです。データセンターで使うな騒動もあったし、Cuda は、もうええんですわ。
そしたら、boost::compute というのがあって、OpenCL を使えるらしいのです。
チュートリアルを macbook pro でコンパイルしてみたら動く感じだったんで、本当に速いのかチェックしてみました。

コンパイルは、brew install boost してある状態で、こんなん。
g++ tutorial3.cpp -I /usr/include -framework OpenCL -std=c++11 -lboost_timer
チュートリアルを少し弄ってあります。
#include <vector>
#include <algorithm>

#include <boost/compute/algorithm/transform.hpp>
#include <boost/compute/container/vector.hpp>
#include <boost/compute/functional/math.hpp>

#include <iostream>
#include <cmath>
#include <boost/timer/timer.hpp>

namespace compute = boost::compute;

int main()
{
    // get default device and setup context
    compute::device device = compute::system::default_device();
    compute::context context(device);
    compute::command_queue queue(context, device);

    std::vector<float> host_vector(100000000);

    boost::timer::cpu_timer timer;

    float n = 1.0f;
    std::generate(host_vector.begin(), host_vector.end(), [&n]() { return n += 1.0f; });
    // generate random data on the host
    //std::generate(host_vector.begin(), host_vector.end(), rand);

    timer.start();

    // create a vector on the device
    compute::vector<float> device_vector(host_vector.size(), context);

    // transfer data from the host to the device
    compute::copy( host_vector.begin(), host_vector.end(), device_vector.begin(), queue );

    // calculate the square-root of each element in-place
    compute::transform(
        device_vector.begin(),
        device_vector.end(),
        device_vector.begin(),
        compute::sqrt<float>(),
        queue
    );

    // copy values back to the host
    compute::copy( device_vector.begin(), device_vector.end(), host_vector.begin(), queue );
    
    timer.stop();
    
    std::cout << "GPU: " << timer.format() << std::endl;

    n = 1.0f;
    std::generate(host_vector.begin(), host_vector.end(), [&n]() { return n += 1.0f; });
    
    std::sqrt<float>(n);
    
    timer.start();
    std::transform( host_vector.begin(), host_vector.end(), host_vector.begin(), static_cast<float (*)(float)>(std::sqrt));
    timer.stop();
    std::cout << "CPU: " << timer.format() << std::endl;
    
    //for( float x: host_vector) { std::cout << x << ","; }

    return 0;    
}
元は 10000 個の配列演算だったんですが、それだと
GPU:  0.078395s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
CPU:  0.000097s wall, 0.000000s user + 0.000000s system = 0.000000s CPU (n/a%)
メモリ転送の処理に時間がかかって効果を確認できず。
100000000 個の配列演算で比較すると
GPU:  0.367576s wall, 0.000000s user + 0.170000s system = 0.170000s CPU (46.2%)
CPU:  0.819997s wall, 0.820000s user + 0.000000s system = 0.820000s CPU (100.0%)
ようやく効果が確認できました。

追記: host_vector size が 1000000000 -> 100000000 に訂正しました

2018年6月4日月曜日

Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'. 備忘録

どこかに書き留めないと、また調べる事になりそうなので、備忘録。

ある日突然、AndroidStudioでビルドをしようとすると、こんなメッセージが出てビルドできない。
Configuration 'compile' is obsolete and has been replaced with 'implementation' and 'api'.
It will be removed at the end of 2018. For more information see: http://d.android.com/r/tools/update-dependency-configurations.html

はい、compile は deprecated になり、implementation コマンドに変更されました。
以下のように書き換える必要があります。
dependencies {
    //compile files('../../Ref/Java/android-support-v4.jar')
    //compile 'com.android.support:support-v4:18.0.0'
    implementation 'com.android.support:support-v4:18.0.0'

    //compile files('../../Ref/Java/foo.jar')
    implementation fileTree(dir: '../../Ref/Java', include: 'foo.jar')
    //compile files('../../Ref/Java/bar.jar')
    implementation fileTree(dir: '../../Ref/Java', include: 'bar.jar')
}

2018年4月15日日曜日

tiny-dnn で遊ぼ (AutoEncoder)

#include "tiny_dnn/tiny_dnn.h"

namespace td = tiny_dnn;

#include "AudioFile.h"

#include <vector>
#include <random>

//Some traning variable 
const int SAMPLE_NUM = 1024;   //How much traning samples
const int WINDOW_SIZE = 2048;  //How long is each sample
const int BATCH_SIZE = 16;     //How many samples per batch
const int NUM_EPOCHS = 2048;   //How much epoch we want to run

int main()
{

  //Create a sample buffer
  std::vector<td::vec_t> samples(SAMPLE_NUM, td::vec_t(WINDOW_SIZE));

  AudioFile<float> audioFile;
  audioFile.load("a.wav"); //Load audio
  auto& data = audioFile.samples[0]; //Just use the first channel

  //Create a RNG and a distribution to generate random numbers
  std::mt19937 rng;
  std::uniform_int_distribution<int> dist(0, data.size()-WINDOW_SIZE);
  //Generate samples
  for(auto& v : samples)
  {
    int offset = dist(rng);//Generate random offsets
    auto start = data.begin() + offset;
    //Copy data from source to sample
    std::copy(start, start+WINDOW_SIZE, v.begin());
  }
  
  //Create an autoencoder
  td::network<td::sequential> net;
  net << td::fully_connected_layer(WINDOW_SIZE, 512) << td::tanh_layer()
    << td::fully_connected_layer(512, WINDOW_SIZE);
  
  //Helper class
  td::progress_display disp(SAMPLE_NUM);
  td::timer t;
  
  int currentEpoch = 0;
  
  //Callbacks when a mini bactch is done
  auto onMinibatch = [&]()
  {
    //This updates the progress display
    disp += BATCH_SIZE;  
  };
  
  //Callbacks when an epoch is done
  auto onEpoch = [&]()
  {
    std::cout << "Epoch " << ++currentEpoch << "/" << NUM_EPOCHS << "done. "
      << t.elapsed() << "s elapsed." << std::endl;
      
    //Reset progress display and timer
    disp.restart(SAMPLE_NUM);
    t.restart();
  };
  
  //train the network with absolute(L1) error.
  td::adagrad optimizer;
  net.fit<td::absolute>(optimizer, samples, samples, BATCH_SIZE, NUM_EPOCHS
    , onMinibatch, onEpoch);
  net.save("net");

  //Let's try the network
  std::vector<float> result(data.size());
  for(int i=0;i<data.size();i+=WINDOW_SIZE)
  {
    //Input to the neural network
    td::vec_t input(WINDOW_SIZE);
    //copy data into the input vector
    std::copy(data.begin()+i, data.begin()+i+WINDOW_SIZE, input.begin());

    //Run the neural network then copy it to the result buffer
    td::vec_t predict = net.predict(input);
    std::copy(result.begin()+i, result.begin()+i+WINDOW_SIZE, predict.begin());
  }
  
  //Save the audio we ganarated
  AudioFile<float> saveFile;
  AudioFile<float>::AudioBuffer buffer(1);
  buffer[0] = result;
  audioFile.setAudioBuffer(buffer);
  audioFile.save("audioFile2.wav");
}
コンパイル
g++ auto_encoder.cpp -I . -std=c++14 AudioFile.cpp
実行
...

0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Epoch 336/2048done. 40.7405s elapsed.

0%   10   20   30   40   50   60   70   80   90   100%
|----|----|----|----|----|----|----|----|----|----|
***************************************************
Epoch 337/2048done. 42.2788s elapsed.

...
wavファイルによると思うが、3日ぐらいかかりそうな勢い

tiny-dnn で遊ぼ (XOR)

チュートリアル XOR
#include <tiny_dnn/tiny_dnn.h>
#include <vector>

namespace td = tiny_dnn;
namespace tda = tiny_dnn::activation;

int main() {
  td::network<td::sequential> net;
  net << td::fully_connected_layer(2,3) << td::sigmoid_layer()
  << td::fully_connected_layer(3,1) << td::sigmoid_layer();

  std::vector<td::vec_t> trainIn = {{0,0}, {0,1}, {1,0}, {1,1}};
  std::vector<td::vec_t> trainOut = {{0}, {1}, {1}, {0}};

  td::gradient_descent optimizer; //(0.53);
  optimizer.alpha = 0.53f;
  net.fit<td::mse>(optimizer, trainIn, trainOut, 1, 1000);
  net.save("net");
  std::cout << net.predict({0,0})[0] << std::endl;
  std::cout << net.predict({0,1})[0] << std::endl;
  std::cout << net.predict({1,0})[0] << std::endl;
  std::cout << net.predict({1,1})[0] << std::endl;

  return 0;
}
出力
0.0411867
0.956243
0.959534
0.037655

2017年12月19日火曜日

Windows 環境変数適用 備忘録

環境変数を値に置き換える
#include <boost/regex.hpp>
#include <string>
#include <iostream>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

std::string getEnvValue(const std::string& str) {
  std::string result;
  std::string inp = str.substr( 1, str.size() - 2 );
  //std::cout << inp << std::endl;
  char buf[ 4096 ];
  DWORD sz = sizeof(buf);
  if( GetEnvironmentVariable( inp.c_str(), buf, sz ) > 0 ) {
    result = buf;
  }
  return result;
}

bool replaceEnv(std::string& str) {
  boost::regex r("(%[a-zA-Z0-9_]+%)");
  boost::smatch m;
  if( boost::regex_search(str, m, r) ) {
    std::string eval = m.str(1);
    std::string sval = getEnvValue( eval );
    while( std::string::npos != str.find(eval) ) {
      str.replace( str.find(eval), eval.size(), sval );
    }
    return true;
  }
  return false;
}

int main(int argc, char* argv[]) {
  std::string str = "%USERPROFILE%\\hoge\\fuga";
  while( replaceEnv( str ) ) {}
  std::cout << str << std::endl;

  

  return 0;
}

2017年12月5日火曜日

MSVCを使ったOSSのビルドについて

C++アドベントカレンダー2017のDAY5の記事になります。


皆さんOSS(オープン・ソース・ソフトウェア)のビルド、どうしてますか?
Linux 系だとパッケージメンテナーが存在していて、apt get コマンドや yum コマンド一発でビルドされたライブラリが取得できますし、プラットフォームが更新されれば、update をかませば一括してライブラリもそれに合わせて更新されます。
それに大抵は ./configure し、make し、make install で済んでしまいます。

Windows 環境でOSSを利用したい時、どうしてますか?
僕は毎回ソースをダウンロードしてから、install.txt や readme.txt やサイトを検索してビルド方法を試行錯誤していました。一度ビルドしてしまえば、当面ビルドの必要無いですしね?
現状を振り返ってみて、気がついてみれば、結構いろんなOSSを利用していました。
それに、会社ではサポートしなければならないOS等の関係もあり、長らくVisual Studio 2005を使っていました。情勢が変わって、Windows 7 の期限も近づいており、さすがに Visual Studio 2010 に切り替えました。これを契機にOSSのビルドを自動化して時間の効率化を図ろうと決意しました。

 ちょっと脱線しますが、自動化しようと思った動機について、もう少し書こうと思います。

 ひとつは、MSの提供するライブラリよりもOSSに依存した方が安全だと思った事です。ISAPI が C++でサポートされなくなったり、Regex系のライブラリが消えたり、Web系のC++ライブラリがサポートされなくなったり。特にSoapを使った独特のIDL言語を使った機構がサポートされなくなったのは、かなりの痛手です。MSのライブラリに依存することは、危険です。使いやすいからWTLでアプリを組んでいましたが、リモート・アプリケーションでのプリンタが認識できない問題で、印刷コモンダイアログを自作する羽目になりました。幸いWTLは、まだメンテナンスが行われており、Issues 等を提案すると取り込んでもらえる状況なのが救いです。Regex系のライブラリが消えた時は、移植で死にそうになりました。Soapがサポートされなくなった時は、MSはC#が大切でC++なんか気にしちゃいないと実感しました。

 もうひとつは、自社で開発している既存のソフトウェアを32bit環境から64bit環境へ移行する目論見も出てきました。移行する時にOSSライブラリを個々に調べてビルドしていたら大変です。

 最後は、あわよくばプルリクエストをもらって楽しよう共闘できると思ったからです。そんなプロジェクト、どこにも無いですし、それなりに価値があるのではないかと思っています。

そうやって作成したのが、こちら
build-oss-library-on-windows
です。

 自動化するにあたっては、いろいろと躓きました。Visual Studio の IDE を使ってコンパイルしなければならないのが面倒で調べたところ、msBuild というコマンドで IDEのプロジェクトをビルドできる事が分かりました。ところが、このIDEはバージョン依存で正しいビルドツールを指定しないとエラーでビルドできません。正しいビルドツールの番号、気が狂ってます。Visual C++ のバージョンを判定するバッチファイルの修正履歴を見ていただければ、わかると思いますが、現実は予想の斜め上を行ってました。信じらない事に Microsoft からVisual C++のバージョンに関する公式の表がどこにも掲載されていません
Visual Studio 製品名VC通称ツールセットのバージョンコメント
Visual Studio 2003VC7v70
Visual Studio 2005VC8v80
Visual Studio 2008VC9v90
Visual Studio 2010VC10v100
Visual Studio 2012VC11v110
Visual Studio 2013VC12v1202015がVC14だからVC12で合ってるか調べる羽目になったやんけ(#^ω^)ピキピキ
Visual Studio 2015VC14v140なんで一個バージョン飛んでるねん?
Visual Studio 2017VC15v141v141って殺すぞ何ぞ?(^ω^)
また、*.sln プロジェクトファイルは、それぞれのバージョンに合わせなければなりません。幸い devenv /upgrade でコマンドラインからアップグレードできるのが救いです。

 今のところ Visual Studio 2010 win32 プラットフォームでしかビルド検証されていない状況ですが、ドキュメントを参考に是非、利用してみてください。特に自前で、コツコツと毎回ビルドされている方には使ってみて欲しいです。時間の節約になると思います。そして共闘しましょう٩( 'ω' )و

 最後に…
安全という名の緊縛の言語 Java氏ね Java氏ね Java氏ね 

追記:コメント頂いた。vcpkg にて、凄い勢いでビルドパッケージが構築されているので、Visual Studio 2015 以上を使う場合には、vcpkg を利用した方が良さそうです。
尚、Visual Studio を巡るバージョン情報は、@yumetodo さんにより更新されております(これ、凄い労力だな…)