2021년 12월 3일 금요일

Go Ethereum 구축

 # Go 컴파일러 설치

https://go.dev/doc/install 에 가서 설치 파일이 아닌 바로 시스템에 맞은 바이너리를 다운로드한다.

처음에 시스템의 파티션을 너무 작게 설정하는 바람에 사용자 계정의 루트에 설치해야 한다.

어짜피 나혼자 쓰는 시스템이니 이렇게 해 놓아도 무방하다.

$ rm -rf $HOME/daysleep/go && tar -C $HOME/daysleep -xzf go1.17.3.linux-amd64.tar.gz

 자 설치는 다 되었으니 시스템 경로에 go를 추가한다.

$HOME/.profile에 다음의 라인들을 추가한다.

if [ -d "$HOME/go/bin" ] ; then
    PATH="$HOME/go/bin:$PATH"
fi

이제 터미널을 열어서 설치와 설정이 제대로 되어 있는지 확인해 보자. 다음과 같이

$ go version

go version go1.17.3 linux/amd64
 

# 간단한 Go 언어 문법 살펴보기

 

# Go Ethereum 설치

 go 는 자체 빌드 절차를 가지고 있는 듯하다 그냥 보기엔 git이 통합되어져 있는 것 같다.

아무튼 이질적이라 거부감이 든다. 그래서 전통적인 git으로 땡겨와서 make로 설치하는 방법이 정신건강에 좋을 것 같다.

$ git clone https://github.com/ethereum/go-ethereum.git
$ cd go-ethereum
$ make geth

위와 같이 문제없이 수행되면 geth라는 실행파일이 go-ethereum/build/bin에 생성되고 시스템에서 사용할 수 있게 시스템 PATH에 추가해 주면 된다.

아직은 geth라는 것이 뭔지 모르겠지만, 시작은 geth로 시작해 보아야 겠다. 나머지 많은 프로그램 꾸러미들이 있는데 그걸 다 생성하려면 make all 하면 되지만 잠시 미루어 두기로 하자. 머리 아프다.

오 이런 $GOPATH를 요구한다. 이건 뭐하는 놈인지?

$ go env 하니깐 GOPATH="/home/daysleep/go" 이라고 나오네 아마도 go로  build 안해서 생기는 추가 요구사항인것 같다.

그럼 다시 $HOME/.profile의 go 설정에 추가해 주자 다음과 같이.

if [ -d "$HOME/go/bin" ] ; then
    PATH="$HOME/go/bin:$PATH"
    GOPATH="$HOME/go"
fi

멀쩡한 터미널 닫고 다시 열어서 반복해야 겠다. 오 아니다. 이걸로 해결이 안된다. 

역시 수작업은 문제가 있다. 설치한 go의 환경을 지우고 debain 패키지로 제공되는 gccgo-go를 설치해야 결과를 볼 수 있다.

$ apt install gccgo-go

그리고 다시 위의 설치를 다시 수행해 본다. 뭔지 모르지만 엄청 많은 패키지들을 git으로 땡겨오고 난리다. 그래도 안된다.

이제 잘란다.








 

2021년 8월 1일 일요일

Line Scan Imaging을 위한 buffer 다루기와 Thread의 설계

# Memory 설계

기본적으로 메모리 사용량의 효율성 보다 서로 다른 Thread가 하나의 메모리 공간을 가지고 경쟁하는 상황을 피하기 위해서,

라인 스캔된 영상들은 하나의 영역을 구성하는 기본 영상을 저장하는데 필요한 크기보다 큰 circular buffer(boost::circular_buffer)에 차곡차곡 쌓아 놓아야 한다. 이를 통해서 영상을 획득하는 Thread(Acquisition Processing)는 circular buffer에 적재만 하고 ciruclar buffer가 어떻게 사용되는지는 고려하지 않아도 된다. 그리고 영상이 완성된 이후의 영상처리 기능을 분산하기 위해서 라인 스캔된 영상단위로 처리할 수 있는 영상처리를 수행하고 처리된 결과를 저장할 추가적인 circular buffer를 마련해서 computing cost를 분산시킨다.

# Thread 설계 

라인 스캔 영상을 처리학 위해서 최소한 3개의 Thread가 필요하다. 첫째는 라인 스캔된 영상을 획득하고 circular buffer에 적재하는 Thread(+가능하다면 라인스캔 단위로 처리할 영상처리를 수행), 둘째는 하나의 기본단위 영상 크기에 대한 영상처리 thread, 그리고 마지막 셋째는 영상 처리 결과를 30혹은 60hz 주기로 GUI에 뿌려주는 Thread로 구성하면된다.

이와 같은 Thread가 순차적으로 동작하도록 하기 위해선 QThreadPool과 QRunnable이라는 Qt 인스턴스를 활용해야한다.

# 최적화

속도의 문제가 발생할 수 있는 우려되는 영역은 영역 단위의 영상처리 Thread의 수행 속도이다. 이 부분의 우려를 불식시키기 위해서는 병렬처리를 고려해 볼 수 있다. 기본적으로 OpenCV를 사용할 경우 GPU나 SIMD를 활용한 Custom 라이브러리를 사용하는 것을 첫번째로 고려하고 아니면 수작업으로 SIMD나 CUDA를 이용한 방법을 고려해보자.

# 배워야할 거리들

boost::circular_buffer, QThreadPool, QRunnable, OpenCV with SIMD, and CUDA enabled, SIMD, CUDA


2021년 2월 20일 토요일

벤쳐기업 설립을 위한 사전 조사.

 우선 공공기관에서 벤쳐기업 설립 인증 업무가 사설기관으로 통합 이관 된 것 같다. 그래서 우선적으로 회원가입부터 해야 한다.

1. 벤쳐인(https://www.venturein.or.kr) 회원가입

 그리고 더 알아보기 이전에 왜 벤쳐로 기업을 설립하고자 하느냐 하는 질문에 대한 해답을 찾아야 했다. 그래서 "벤처기업육성에관한특별조치법 제2조"에 대해서 찾아 보았다.

2. 제2조의 2. 벤쳐기업의 요건 요약

전제 조건으로 중소기업을것. 그리고 그런저런 투자로 설립된 기업의 자본금 대비 투자금의 비율이 일정정도 이상인 기업을 일컫는것 같다. 거기에 덧붙여 벤쳐기관확인기관이 성장성이 우수한 것으로 평가받는 기업(단, 창업후 3년 미만인 기업의 경우 자본금 대비 투자금의 비율의 적용을 받지 않는다.)

여기서, 벤쳐기관확인기관에 우선적으로 문의해 보아야할 사항인것 같고 그 기관이 벤쳐인으로 사료된다.

그리고 살펴보다가 교육공무원의 겸임과 휴직에 대한 내용인 것 같다. 결론적으로 기관장의 승인만 있으면 얼마든지 가능하다고 본다.

3. 고등교육기관 장의 승인만 있으면 벤쳐기업의 대표나 임원으로 겸임을 하거나 불이익 없이 휴직 복직이 가능한 것 같다.

또, 교육기관이나 연구소의 창업보육센터에 들어가는 이유는 복잡한 법율 규제의 적용을 받지 않는 것 같다. 

4. 국가로부터의 시설비용지원, 건축금지에 대한 특례, 각 종 부담금의 면제

자 그럼 벤쳐인에 가서 다음 사항에 대해서 구체적으로 살펴보아야 겠다.


# 벤쳐 확인 요건 확인

우선 벤쳐의 유형

1. 벤쳐 투자 기업 - 투자기업과 벤쳐기업이 일반적으로 매칭되지는 않지만, 벤쳐투자도 벤쳐기업만큼의 해택이 주어지지 않으면 이루어지지 않는다는 점을 생각해보면 수긍이 간다.

2. 연구 개발 기업 - 기업부설연구소 보유기업을 이야기 하는 것 같다. 아직 기업 설립도 안된 상황이기 때문에 이것 고려할 수 없는 경우인 것 같다.

3. 기술평가보증기업 - 기보(기술보증기금)(기술평가보증에 한함)으로부터 보증 또는 중진공(중소벤쳐기업진흥공단)으로부터의 대출을 받은 기업은 벤쳐로 인증받기 수월할 것 같다. 이것도 마찬가지로 이미 창업한 회사에 해당하는 것 같다. 그래서 이것도 해당사항은 아닌것 같다.

4. 기술평가대출기업 - 이 유형도 기술평가보증기업과 유사한 것 같다. 마찬가지로 해당사항이 아닌것 같다.

5. 예비벤쳐기업 - 법인설립 또는 사업자설립을 준비 중인 기업, 딱 지금 나의 상황에 딱 맞아 떨어지는 항목이다. 그런데 한 가지 더 추가사항이 있다. 기술 및 사업계획이 기보(기술보증기금)나 중진공(중소벤쳐기업진흥공단)으로 부터 기술성이 있는 것으로 평가받아야 한다는 조건을 만족해야 한다. 

** 기술 및 사업계획을 기술보증기금이나 중소벤쳐기업진흥공단에서 기술성 평가를 받아야 한다. **

그리고 주의 사항은 예비벤쳐기업은 법적으로 벤쳐기업은 아니라는 점이다. 예비 벤쳐 기업은 창업전에만 적용받는 조항이고, 창업 이후에는 기존의 창업한 기업의 벤쳐 유형으로 인증 받아야 한다. 아마도 연구 개발 기업, 기술평가보증기업, 기술평가대출기업 등등.

우선 예비벤쳐인증 받고 법인 설립하고 중소기업벤쳐진흥공단에서 기술을 인정받고 대출을 받아야 벤쳐기업으로 설립이 가능한 것 같다. 그럼 벤쳐기업으로 인증받기 위한 신청 절차에 대해서 살펴본다. 그리고 나중에 법인 설립에 대해서 반드시 알아 봐야 할 것 같다.


# 벤쳐 확인 신청 절차

벤쳐인 예비벤쳐기업의 수수료 50만원 + 나중에 법인 설립후 또 50만원의 수수료가 소요됨 최소한 100만원을 벤쳐인에 수수료로 사용해야 한다.

벤쳐인 회원가입 ---> 서류검토, 현장점검 ---> 벤쳐확인위원회의 심의/의결 ---> 사무국의 확인서 발급

* 혁신성장기업의 평가 지표는 아직 정해지지 않은 것으로 파악됨

무엇보다도 사업계획서를 잘 만들어야 겠다. 사업계획서..............그리고 현금........

각종 서류 형식은 다음의 사이트에서 다운로드하고 준비해야 한다.

https://www.venturein.or.kr/venturein/petition/C18000.jsp



2021년 2월 16일 화요일

Flutter에서의 Layout

 내가 아는 선에서 이야기 하자면 Qt의 QHBoxLayout과 QVboxLayout에 해당하는 Flutter의 Layout에 대해서 들여다 본다. 

Qt의 Layout과 다르게 Flutter의 Layout은 정렬할 수 있는 항목에 제한이 있다. 내용을 살펴보면 굳이 구분해 가며 인지할 필요없이 당연하지 라고 말할 것이다.

* Center, Container - child라는 항목으로 단지 한개의 항목만 정렬한다. Center는 가운데 정렬로 알겠는데 Container는 아마도 Center안에 여러개를 넣기 위해서 도입된 더미 Layout이라고 추정해 본다.

* Row, Column, ListView, Stack - 앞의 둘은 각각 Qt의 QVBoxLayout, QHBoxLayout에 해당한다. 주의해야할 것은 Row, Column이라는 이름에 선입겸을 갖고 사용하면 큰일 난다. 한번 확인해 보고 사용해야 실수를 줄일 수 있다. Row와 Column이라는 지칭하는 주체가 구분되어지는 칸의 유형을 의미한다라고 나는 이해했다. 그리고 처음 보는 ListView, Stack이 있다. List는 그냥 나열되는 것이고 Stack은 화면의  Z축 방향으로 쌓는 것을 의미하는 것 같다.

아직은 추측성이 많다 하나하나 확인해 나아가겠다.

Flutter에서 StatelessWidget과 StatefulWidget with State의 차이

#  Stateless Widget

내부 변수의 변경 사항이 다른 메서드에 반영되지 못하는 특성을 가지고 있다.

아직까지의 파악으로는 UI의 디자인을 전게해나아는데 특화해서 사용하는 Widget으로 파악된다.


# StatefulWidget

통상 State Widget을 내부 객체로 포함하며, 

State Widget의 내부 변수의 변경사항에 setState() 선행 매서드를 통해 다른 구성요소에 전달되도록 하는 메카니즘을 가지고 있다.


# Stateless Widget과 StatefulWidget(State)의 예제 

MyApp이라는 Flutter Tutorial에 두번째로 출현하는 예제이다. 여기서, MyApp자체가 StatelessWidget을 상속받아서 생성되어 있다.(뭐 딱히 동적으로 변경해야할 변수들을 가지고 있지 못하다.) 그리고 StatelessWidget의 build 메서드를 override(덮어 씌우기)해서 새롭게 MaterialApp을 생성하고 있다.

(MaterialApp은 구글이 밀고 있는 Material Design을 계승하는 Widget이라고 한다.)

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

/*
void main() {
runApp(MyApp());
}
*/

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData(
primaryColor: Colors.white,
),
home: RandomWords(),
);
}
}

아직 Dart언어를 모르기 때문에 하나 짚고 넘어가야할 사항이 있다. main 함수의 형태이다.

주석으로 처리되어 있는 main함수는 익히 알고 있는 C 언어 형태의 서술이고 아래의 '=>'로 엮여진 main함수는 아마도 한줄짜리로 표현한 Dart 언어 문법인 것 같다. (뭐 시작을 C언어와 유사하다고 해서 들여다 보고 있는 형편이라서 과감하게 추정해 보자면 Lambda 함수인것 같다.)

MaterialApp의 home 섹션은 RandomWords라는 Widget으로 들어차게 만든다.

class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => RandomWordsState();
}

자 여기서, RandomWords가 StatefulWidget으로 등장하고 있다. 또 override를 수행한다. 앞에서와 다르게 여긴 createState()로 구현한다. 또 과감하게 추정하자면 둘다 이름이 다를뿐 일종의 생성자 같다. 물론 부모의 기능을 초기화해야 해서 생성자 전체를 override하진 않는 것같다. 아마도 StatelessWidget과 StatefulWidget의 생성자 내부에는 여러개의 Method로 이루어져 있는 것 같다. 그 중 하나를 override하고 있다고 추정하는 바이다.

여기까지, StatelessWidget과 StatelessWidget의 구성이다. 각각  build()와 createState()라는 override를 통해서 구현하고 있다. 이 둘의 이름에서 알 수 있듯이 State가 없고 있고의 차이가 있다.

아직 설명 안된 구석이 있는데 그것은 RandomWordState라는 Widget이다.


class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
actions: [
IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
]
),
body: _buildSuggestions(),
);
}

Widget _buildSuggestions() {
return ListView.builder(
padding: const EdgeInsets.all(16.0),
itemBuilder: /*1*/ (context, i) {
if (i.isOdd) return Divider(); /*2*/
final index = i ~/ 2; /*3*/
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}

Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
}
);
}

void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
final tiles = _saved.map((WordPair pair) {
return ListTile(
title: Text(pair.asPascalCase, style: _biggerFont)
);
});

final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();

return Scaffold(
appBar: AppBar(
title: Text('Saved Suggestions'),
),
body: ListView(children: divided),
);
},
),
);
}
}

길다. RandomWordsState는 예상했듯이 State로 부터 상속받아서 생성된다. 여기서, 의문점은 State<RandomWords>라는 구문이다. 내가 아는 C언어 선입견을 동원하면 State class를 RandomWords의 타입을 같도록 생성한 template인 것 같다. 말이 어렵다 State가 RandomWords라는 내부 항목을 가지고 작업할 것이다라고 이해하자.

아직 정체가 불확실한 final로 시작하는 변수 생성 이것도 마찬가지 그냥 넘어가자. 그냥 변수다라고만 인지하고 나중에 차차 살펴보자.

첫 번째 Method인 build()는 StatelessWidget에서 보았듯이 일종의 생성자 중 하나라고 보자. 여기서, Scaffold라는 MaterialApp과는 다른 Widget을 만들고 있다. 새로운것들이 많이 등장한다. 우선은 Scaffold라는 것은 AppBar라는 일종의 윈도우의 title bar와 내부항목에 해당하는 body라는 섹션을 가지고 있다. 

먼저 AppBar는 문자로된 title을 가지고 있고 그에 해당하는 동작을 actions에 담고 있다. IconButton을 가지고 뭘 하는 것 같다. 우선 넘어가자. 그리고 body에는 _buildSuggestions()이라는 method로 뭔가 _suggestions이라는 리스트를 만들고 보여주는 것을 수행하는 것 같다.

_buildSuggestions과 엮인 다른 Method는 생략한다. 지친다. 


# 전체 코드

import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';

/*
void main() {
runApp(MyApp());
}
*/

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Startup Name Generator',
theme: ThemeData(
primaryColor: Colors.white,
),
home: RandomWords(),
);
}
}

class RandomWords extends StatefulWidget {
@override
RandomWordsState createState() => RandomWordsState();
}

class RandomWordsState extends State<RandomWords> {
final _suggestions = <WordPair>[];
final _saved = Set<WordPair>();
final _biggerFont = const TextStyle(fontSize: 18.0);

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Startup Name Generator'),
actions: [
IconButton(icon: Icon(Icons.list), onPressed: _pushSaved),
]
),
body: _buildSuggestions(),
);
}

Widget _buildSuggestions() {
return ListView.builder(
padding: const EdgeInsets.all(16.0),
itemBuilder: /*1*/ (context, i) {
if (i.isOdd) return Divider(); /*2*/
final index = i ~/ 2; /*3*/
if (index >= _suggestions.length) {
_suggestions.addAll(generateWordPairs().take(10));
}
return _buildRow(_suggestions[index]);
}
);
}

Widget _buildRow(WordPair pair) {
final alreadySaved = _saved.contains(pair);
return ListTile(
title: Text(
pair.asPascalCase,
style: _biggerFont,
),
trailing: Icon(
alreadySaved ? Icons.favorite : Icons.favorite_border,
color: alreadySaved ? Colors.red : null,
),
onTap: () {
setState(() {
if (alreadySaved) {
_saved.remove(pair);
} else {
_saved.add(pair);
}
});
}
);
}

void _pushSaved() {
Navigator.of(context).push(
MaterialPageRoute<void>(
builder: (BuildContext context) {
final tiles = _saved.map((WordPair pair) {
return ListTile(
title: Text(pair.asPascalCase, style: _biggerFont)
);
});

final divided = ListTile.divideTiles(
context: context,
tiles: tiles,
).toList();

return Scaffold(
appBar: AppBar(
title: Text('Saved Suggestions'),
),
body: ListView(children: divided),
);
},
),
);
}
}


2021년 1월 3일 일요일

Repair the broken pip in python 3.8 venv against python 3.9 as system default

Suddenly distutils used for venv of python3.8 is disappeared after system updated.

In the look into /usr/lib/python3.8/distutils, many files are missing.

I found the workaround at https://askubuntu.com/questions/1239829/modulenotfounderror-no-module-named-distutils-util

My solution is that distutils in python3.8 has to be copied from distutils in python 3.9.

root@T480s:~# cp -r /usr/lib/python3.9/distutils /usr/lib/python3.8


2021년 1월 2일 토요일

VGG16 for 1D regression

 1. Build Model


2. Prepare the data using scaler

3. Do Training

4. Result