fortran66のブログ

fortran について書きます。

【ニュース】Julia ヨイショ記事と思いきや、珍しく Fortran 褒められる

意外に公正で草

どうせ julia 上げ記事かと思ってみてませんでしたが、覗いてみると意外に Fortran も上げられてました。 お金が絡むとシビアです。

towardsdatascience.com

要旨

During the last months, I have been working intensively on quantitative intraday strategies. As a side result, I have tested workflows for similar tasks in Python, C, Fortran and Julia. Here are my findings.

  1. I work on projects related to instruments trading (i.e. I design and simulate derivatives market algorithmic/quantitative strategies).
  2. I have not used Machine Learning or AI techniques in these strategies, just plain/vanilla statistics and simulation.
  3. Handled data sets are large but not huge, normally my simulations cover 30 million records data sets per asset/instrument, every data is used several times, and I do parametric and Monte Carlo analysis. This implies a large number of iterations.
  4. I am not an expert programmer and I am not interested in becoming one, I just want to focus on the market logic and the strategies that exploit profitable edges.

  1. I need a language that can deal easily and without efforts with large data sets.
  2. I need speed.
  3. I do not need that much speed to require multi-core or parallel processing.
  4. I do not need —at this time— Machine Learning or AI libraries.  

言語

一部引用 (太字は私の強調)

Fortran is now a niche language (currently around position 30 in the list of most used programming languages in the world) but it still has an active community in specialised fields such as high-energy physics, astrophysics and molecular dynamics. Together with C, it is also the main programming language for supercomputing. Standards such as OpenMP and MPI which define ways to distribute computing among cores and distributed computers are always implemented first for C and Fortran.  

 

While modern Fortran has nothing to do with what most people think (upper case code, goto instructions and punched cards), its syntax shows some age. It allows a good code structure and it is quite easy to learn (even to master). My experience while porting the last simulation to Fortran was that coding was easy and that specifically, the algorithmic parts written in C were much easier to code in Fortran. The structured code was also superior to Python, although this is a personal opinion and I know many would disagree with this statement.
  

There were also some problems: a harder integration with graphical tools and the fact that variables need to be declared in advance (something I do not like) but in my opinion, the main issue was that debugging was hard because Fortran at the end ends up calling a C compiler. So my experience is that debugging Fortran was a bit harder than debugging the Python+C solution.
 

On the positive side, Fortran also had some unique solutions to deal with array and structured data, which includes custom index (array[2000:2020] is a valid index range, something that no other language can achieve), vector operations and simple ways to initialise variables and structures.
 

Fortran or C is the way to go if you need speed and plan to do analysis requiring multi CPU and/or multi-core —HFT industry uses C++ intensively — , and it is not casual that both AMD and Intel keep their compiler divisions selling both C++ and Fortran compilers. But if you do not need that much speed, it might be better to trade off some performance for a more friendly environment easier to debug and the possibility to use DataFrames.
 

Fortran performance is astonishing. Fortran was able to read a whole year of prices from a CSV file, convert them to integers to avoid loss of precision, round them down to contract ticks and store them into memory in around 1 second. This means that a strategy using 20 years of 1-minute prices would be loaded into memory and ready to be used in 20 seconds. It simply outperforms by far any other language I tried.
 

Its native usage of arrays also made calculations very fast too. In many operations Fortran outperforms C. Believe it or not, 60 years later, it is still the number one number cruncher and its structure is well suited for simulation problems because it was designed with that kind of problems in mind.

pointer function で連想配列 改

以前、Fortran2008 の pointer function を用いて、簡単な連想配列を作ってみましたが、ハッシュ法を N.Wirth の『アルゴリズム+データ構造=プログラム』 中の方法を用いてみました。キーは散らばっているでしょうか?

関数名を配列名のように使うので、このままでは連想配列ごとに関数を定義と駄目なので、何かいい手はないものか考えたいと思います。何か物憂く面倒くさいので、考えていませんし思いついていません。ポインターが返り値という関数なので、使い方をよく理解していない気がします。

fortran66.hatenablog.com

N.Wirth, Algorithms + Data Structures = Programs

Oberon 版 無料本 第五章 Key Transformations (Hashing)

http://www.ethoberon.ethz.ch/WirthPubl/AD.pdf

Modula-2 版 訳本

アルゴリズムとデータ構造

アルゴリズムとデータ構造

Pascal 版 原本

Algorithms + Data Structures = Programs (Prentice-Hall Series in Automatic Computation)

Algorithms + Data Structures = Programs (Prentice-Hall Series in Automatic Computation)

ソース・プログラム

    module hash_m
        implicit none
     !   private
     !   public :: ia
        
        integer, parameter :: nhash = 73
        type :: t_key
            character(len = :), allocatable :: key  
        end type t_key
        type (t_key)    :: keyc(nhash)  
        integer, target :: vals(nhash) = 0  
    contains
        pure integer function ihash(text) 
            character(len = *), intent(in) :: text
            integer :: i
            ihash = 0
            do i = 1, len_trim(text)
                ihash = mod(256 * ihash + iachar(text(i:i)), nhash)
            end do
            ihash = ihash + 1
        end function ihash  
       
        
        function ia(text) result(ires)
            character(len = *), intent(in) :: text
            integer, pointer :: ires 
            integer :: key, loc, ihop
            ihop = 1
            key = ihash(text) 
            do
                if (.not. allocated(keyc(key)%key)) then
                    keyc(key)%key = trim(text)
                    ires => vals(key)
                    exit
                else if (keyc(key)%key == trim(text)) then 
                    ires => vals(key)
                    exit
                else ! collision
                    key = mod(key + ihop, nhash) + 1   
                    ihop = ihop + 2
                    if (ihop == nhash) stop 'associative array exhausted!' 
                end if
            end do  
        end function ia      
    end module hash_m
    
    
    program Hash
        use hash_m
        implicit none
      
        ia('a') = 41
        print *, ia('a')
        ia('a') = 100
        print *, ia('a')
        ia('b') = 200
        print *, ia('a') + ia('b')
      
        ia('FORTRAN I') = 1957
        ia('FORTRAN II') = 1958
        ia('FORTRAN IV') = 1961
        ia('FORTRAN 66') = 1966
        ia('FORTRAN 77') = 1978
        ia('Fortran 90') = 1991
        ia('Fortran 95') = 1997
        ia('Fortran 2003') = 2004
        ia('Fortran 2008') = 2010
        ia('Fortran 2018') = 2018
        
        ia('Gold') = 1488
        ia('Silver') = 17
        ia('Platinum') = 946
        ia('Palladium') = 1590
        ia('Rhodium') = 4700
      
        block
          integer :: i
          do i = 1, nhash
              print '(i3,a,a20,a,i10)', i, ':', keyc(i)%key, '=>', ia(keyc(i)%key)
          end do    
       end block
    end program Hash

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

実行結果

gfortran 7 以上で、 ifort V.17 以上くらいで行けると思います。 

          41
         100
         300
  1:                    =>         0
  2:             Rhodium=>      4700
  3:                    =>         0
  4:                    =>         0
  5:            Platinum=>       946
  6:                    =>         0
  7:                    =>         0
  8:                    =>         0
  9:           Palladium=>      1590
 10:                    =>         0
 11:                    =>         0
 12:                    =>         0
 13:                    =>         0
 14:                    =>         0
 15:                    =>         0
 16:                    =>         0
 17:                    =>         0
 18:                    =>         0
 19:                    =>         0
 20:                    =>         0
 21:                    =>         0
 22:                    =>         0
 23:                    =>         0
 24:                    =>         0
 25:                   a=>       100
 26:                   b=>       200
 27:        Fortran 2018=>      2018
 28:                    =>         0
 29:                    =>         0
 30:                    =>         0
 31:          FORTRAN 77=>      1978
 32:                    =>         0
 33:                    =>         0
 34:                    =>         0
 35:                    =>         0
 36:                    =>         0
 37:                    =>         0
 38:                    =>         0
 39:                    =>         0
 40:                    =>         0
 41:                    =>         0
 42:           FORTRAN I=>      1957
 43:                    =>         0
 44:          Fortran 90=>      1991
 45:                    =>         0
 46:                    =>         0
 47:          Fortran 95=>      1997
 48:              Silver=>        17
 49:                    =>         0
 50:                    =>         0
 51:                    =>         0
 52:                    =>         0
 53:                    =>         0
 54:                    =>         0
 55:                    =>         0
 56:                    =>         0
 57:                    =>         0
 58:          FORTRAN II=>      1958
 59:                    =>         0
 60:        Fortran 2003=>      2004
 61:                    =>         0
 62:                    =>         0
 63:        Fortran 2008=>      2010
 64:                    =>         0
 65:                    =>         0
 66:          FORTRAN 66=>      1966
 67:                    =>         0
 68:                    =>         0
 69:                    =>         0
 70:                    =>         0
 71:          FORTRAN IV=>      1961
 72:                    =>         0
 73:                Gold=>      1488

【ニュース】金のトイレ盗まる!

トランプ大統領に貸与の申し出があった 18 金トイレ盗まる!

英美術館で使用可能状態で展示中に盗まれたようです。

www.kitco.com

f:id:fortran66:20190915012304p:plain
America

According to media reports, the working toilet was reported stolen from the Blenheim Palace in Oxfordshire, England. The museum is also the home where former prime minister Winston Churchill was born.       

The fully functional golden toilet, named "America," was created by Italian artist Maurizio Cattelan. It has been plumbed into the water system and visitors could fully engage with the artwork for three minutes.         

The theft created significant water damage to the museum.              

The toilet gained international recognition when it was installed in the Guggenheim Museum in New York in 2016. A year later, it gained even more notoriety after the Trump administration emailed the Guggenheim and asked to borrow Vincent Van Gogh's 1888 painting "Landscape with Snow." The curator of the famed institution proposed the golden toilet as a counteroffer.

支那人は便器にこびりついた白い石のようなものを削って中華料理の調味料に使うそうなので、食いしん坊の支那人の仕業かと思いましたが、設置後二日目での盗難ということで、食糞目的かも知れません。

【ニュース】「人気の高いプログラミング言語2019」

Fortran さんじゅうはち位

数日前の記事ですが、メモ帳代わりに。

IEEE Spectrum、「The Top Programming Languages 2019」を発表

news.infoseek.co.jp

最後に紹介しているのは、38位にランクインしている「Fortran」。科学計算言語としての莫大な遺産により現在も活発に開発されており、2018年末には最新版がリリースされCとの相互運用性、大規模な並列計算をサポートする改善が組み込まれていると御年60歳を超えるプログラミング言語の健在ぶりを称えている。

IEEE Top Programming Languages: Design, Methods, and Data Sources

https://spectrum.ieee.org/computing/software/the-top-programming-languages-2019

Finally, some older languages are still alive and kicking. In particular, despite being over 60 years old, Fortran still comes in at No. 38, likely due to the enormous legacy power of being the original scientific computing language. The language is still under active development, with the most recent Fortran standard released at the end of 2018, incorporating improved interoperability with C and better support for massive parallel computations.

https://spectrum.ieee.org/static/interactive-the-top-programming-languages-2019

【メモ帳】暇つぶしに Julia で Camplbell-Baker-Hausdorff 計算してみる

Camplbell-Baker-Hausdorff の公式

Camplbell-Baker-Hausdorff の公式という割に、実際の展開式を導いたのはソ連の Dynkin らしいので、この名でいいのかとも思いますが、アカと間違えられて FBI に通報されても困るので、長い物には巻かれましょうw

exp(A)exp(B) = exp(C) の時、C=A+B+[A, B]/2 + ([A,[A,B]]-[B,[A,B]])/12 + [B,[A,[A, B]]]/24+...

Julia 言語での行列積・行列 exp

Julia 言語の行列の積 X*Y は Fortran での matmul(X, Y) になっており、exp(X) も数学的な定義に従って exp のべき展開での行列積になっており、Fortran での行列要素の exp(x_ij) ではないので、これを利用してCamplbell-Baker-Hausdorff の公式に適当な行列を入れて計算して見ることにします。

A=[1 1 
   1 1]
2×2 Array{Int64,2}:
 1  1
 1  1
B = [2 1
     1 2]/10
2×2 Array{Float64,2}:
 0.2  0.1
 0.1  0.2
f(x, y)=x*y-y*x
f (generic function with 1 method)
f(A, B)
2×2 Array{Float64,2}:
 0.0  0.0
 0.0  0.0
exp(A)* exp(B)
2×2 Array{Float64,2}:
 5.53968  4.43451
 4.43451  5.53968
exp(A+B+f(A,B)/2)
2×2 Array{Float64,2}:
 5.53968  4.43451
 4.43451  5.53968
A=[1 1 
   1 0]/10
2×2 Array{Float64,2}:
 0.1  0.1
 0.1  0.0
f(A, B)
2×2 Array{Float64,2}:
  0.0   0.01
 -0.01  0.0 
exp(A)* exp(B)
2×2 Array{Float64,2}:
 1.37607   0.26518
 0.252291  1.24676
exp(A+B+f(A,B)/2+(f(A, f(A, B))-f(B, f(A, B)))/12)
2×2 Array{Float64,2}:
 1.37607  0.265202
 0.25227  1.24676 
exp(A+B+f(A,B)/2+(f(A, f(A, B))-f(B, f(A, B)))/12 -(f(B, f(A, f(A, B))))/24  )
2×2 Array{Float64,2}:
 1.37607   0.26518
 0.252292  1.24676

行列 A, B が可換の時は、当然ながら C=A+B で exp(A)exp(B)=exp(A+B) が成り立ちます。

非可換の時は A, B を 0.1 のオーダーにしたので、交換子は 0.01 のオーダーで、四次の項まで取ることで小数点以下5桁くらいまで一致するようです。まぁそんなものかなという気のする結果ではあります。

Julia 言語では 行列積の関数も適当に書けるので、確かに楽だなと思います。プロトタイプ向きなのがよく分かります。

【メモ帳】Fortran 2018 C言語の相互運用 MFE §21.6 その2

MFE §21.6.5 Allocatable objects

C 側で Fortran の allocatable 変数を deallocate/allocate します。

これを使えば、ZMQ の zmq_msg_init_data も出来ると思います。

fortran66.hatenablog.com

実行結果

gfortran-9/gcc-9

hp8@HP8:~/f2018$ gfortran-9 mfe2165.c mfe2165.f90
hp8@HP8:~/f2018$ ./a.out
 GCC version 9.1.0
 -mtune=generic -march=x86-64

 x
allocatable
rank=2
lowerbound1 extent5 spacing4
allocated
dealloca retcode 0
unallocated
alloca retcode 0
 T           4           5
           0           1
           3           5
   1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000       1.00000000

icc/ifort

hp8@HP8:~/f2018$ icc -c mfe2165.c
hp8@HP8:~/f2018$ ifort mfe2165.o mfe2165.f90
hp8@HP8:~/f2018$ ./a.out
 Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64,
 Version 19.1.0.056 Pre-Release Beta Build 20190321


 x
allocatable
rank=2
lowerbound1 extent5 spacing4
allocated
dealloca retcode 0
unallocated
alloca retcode 0
 T           4           5
           0           1
           3           5
   1.000000       1.000000       1.000000       1.000000       1.000000
   1.000000       1.000000       1.000000       1.000000       1.000000
   1.000000       1.000000       1.000000       1.000000       1.000000
   1.000000       1.000000       1.000000       1.000000       1.000000

ソース・プログラム

program test
    use, intrinsic :: iso_fortran_env
    use, intrinsic :: iso_c_binding
    implicit none
    interface
        subroutine alloc(cdesc) bind(c, name = 'alloc')
            use, intrinsic :: iso_c_binding
            real, intent(in out), allocatable :: cdesc(..)
        end subroutine alloc
    end interface

    real, allocatable :: x(:, :)

    print *, compiler_version()
    print *, compiler_options()
    print *

    print *, 'x'

    allocate(x(5, 5))
    call alloc(x)
    print *, allocated(x), shape(x)
    print *, lbound(x)
    print *, ubound(x)
    x = 1.0
    print *, x
    deallocate(x)

end program test
#include <stdio.h>
#include "ISO_Fortran_binding.h"

int alloc(CFI_cdesc_t *cdesc) {
    CFI_attribute_t attrib = cdesc->attribute;
    if (attrib == CFI_attribute_allocatable) {printf("allocatable\n");};
    if (attrib == CFI_attribute_pointer    ) {printf("pointer\n");};
    if (attrib == CFI_attribute_other      ) {printf("other\n");};



    CFI_rank_t nrank = cdesc->rank;
    printf("rank=%d\n", (int)nrank);

    CFI_dim_t *dim = cdesc->dim;
    CFI_index_t lowerbound = dim->lower_bound;
    CFI_index_t extent     = dim->extent;
    CFI_index_t sm         = dim->sm;
    printf("lowerbound%d extent%d spacing%d\n", (int) lowerbound, (int) extent, (int) sm);


    if (cdesc->base_addr) {
        fputs("allocated\n", stderr);
        int iret = CFI_deallocate(cdesc);
        printf("dealloca retcode %d\n", iret);
    }

    fputs("unallocated\n", stderr);
    CFI_index_t lo[] = {0, 1};
    CFI_index_t hi[] = {3, 5};
    size_t len = 0;
    int iret = CFI_allocate(cdesc, lo, hi, len);
    printf("alloca retcode %d\n", iret);

}

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

Modern Fortran Explained: Incorporating Fortran 2018 (Numerical Mathematics and Scientific Computation)

【メモ帳】○○的の「的」について

杉山孚富 著「漢文故事熟語詳解」より

明治36年 (1903年)初版 明治38年(1905年)訂正6版

面倒なので当用漢字でw カタカナもひらがなに。その他適当に濁点づけ。

てノ部 的 「近来人好んで的の字を用ゆ何々的など云へり此は元来助字にして意味あるにあらず句調を助ける添文字なり晋人好んで馨の字用ひ宋人好んで底の字を用ひ清人好んで兒の字を用ゆるに同じ皆な助字なり音学五書に云う的の字入声となれば則ち「チャク」となり去声に転ずれば「テフ」となり上声に転ずれば「テイ」となる宋人の書中に凡ての語助は皆底(テイ)に作る的の字なしと然らば則ち的も底も同字として助字に用ゆること知るべし」

角川「新字源」には英語の ...tic の意とありますが、19世紀末から20世紀初頭に流行り始めた用法なのでしょうか? 近時支那では助詞の「の」とか of みたいな感じな気がしますが。

「漢文故事熟語詳解」

漢文故事熟語詳解 (金刺芳流堂): 1902|書誌詳細|国立国会図書館サーチ

国会図書館データの年号がずれていて謎。 奥付の方には「受験応用 漢文故事熟語詳解」と。学研の付録みたいな雑然としたオモシロ本。