f2py findet ifort, benutzt ihn aber nicht.

Python in C/C++ embedden, C-Module, ctypes, Cython, SWIG, SIP etc sind hier richtig.
Antworten
Kontrapaganda
User
Beiträge: 7
Registriert: Mittwoch 14. August 2019, 18:25

Sonntag 8. Dezember 2019, 11:14

Liebe Community,
Nachdem ich mit Fortran 95 angefangen habe, wollte ich nun eigentlich mit f2py herumprobieren, um einige Algorithmen zu beschleunigen.
Das OS ist macOS High Sierra. NumPy verwende ich schon länger und Fortran seit Kurzem.
Wenn ich f2py auf mein Script anwenden will, kommt eine ambigue Fehlermeldung.
Als Compiler ist ifort von Intel installiert, den benutze ich sonst auch. Der Intel-C++-Compiler ist ebenfalls installiert.

Code: Alles auswählen

customize Gnu95FCompiler
Could not locate executable gfortran
Could not locate executable f95
customize NAGFCompiler
customize AbsoftFCompiler
Could not locate executable f90
Could not locate executable f77
customize IBMFCompiler
Could not locate executable xlf90
Could not locate executable xlf
customize IntelFCompiler
Found executable /usr/local/bin/ifort
Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.5.281 Build 20190816
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

customize GnuFCompiler
Could not locate executable g77
customize G95FCompiler
Could not locate executable g95
customize PGroupFCompiler
Could not locate executable pgfortran
don't know how to compile Fortran code on platform 'posix'
warning: build_ext: f77_compiler=None is not available.

building 'sieve' extension
error: extension 'sieve' has Fortran sources but no Fortran compiler found
Das ist strange. Zunächst sagt die Ausgabe, dass er den Intel-Fortran-Compiler gefunden hätte.
Anschließend heißt es dennoch, dass kein Fortran-Compiler gefunden worden wäre.

Hat jemand eine Idee?
Benutzeravatar
__blackjack__
User
Beiträge: 4905
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 8. Dezember 2019, 13:07

Was führte denn zu dieser Ausgabe?

Es wird ja nicht gesagt das kein Fortran-Compiler gefunden wurde sondern das f77 nicht gefunden wurde und das der Code nicht weiss wie er unter der Posix-Plattform Fortran Code kompilieren kann. Vielleicht musst Du einfach nur explizit angeben das ifort genommen werden soll.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Kontrapaganda
User
Beiträge: 7
Registriert: Mittwoch 14. August 2019, 18:25

Sonntag 8. Dezember 2019, 13:53

Hm, also ich habe die Optionen „--f90exec=/usr/local/bin/ifort˝ gefunden. Der Pfad ist korrekt, denn damit kann ich ifort tatsächlich benutzen.
Leider ergab der Versuch

Code: Alles auswählen

f2py3 -c --f90exec=/usr/local/bin/ifort sieve.f90 -m sieve
den gleichen Error. Obwohl ich also den Pfad zum Compiler explizit angegeben habe, hat er ihn nicht gefunden.

Code: Alles auswählen

customize UnixCCompiler
customize UnixCCompiler using build_ext
get_default_fcompiler: matching types: '['gnu95', 'nag', 'absoft', 'ibm', 'intel', 'gnu', 'g95', 'pg']'
customize Gnu95FCompiler
Found executable /usr/local/bin/ifort
Could not locate executable gfortran
Could not locate executable f95
ifort: command line warning #10006: ignoring unknown option '-dumpversion'
ifort: command line error: no files specified; for help type "ifort -help"
customize NAGFCompiler
nag: no Fortran 77 compiler found
nag: no Fortran 77 compiler found
Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.5.281 Build 20190816
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

customize AbsoftFCompiler
Could not locate executable f77
absoft: no Fortran 77 compiler found
absoft: no Fortran 77 compiler found
Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.5.281 Build 20190816
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

customize IBMFCompiler
Could not locate executable xlf
ibm: no Fortran 77 compiler found
Could not locate executable xlf95
ibm: no Fortran 77 compiler found
customize IntelFCompiler
Found executable /usr/local/bin/ifort
Intel(R) Fortran Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 19.0.5.281 Build 20190816
Copyright (C) 1985-2019 Intel Corporation.  All rights reserved.

customize GnuFCompiler
Could not locate executable g77
customize G95FCompiler
Could not locate executable g95
g95: no Fortran 77 compiler found
g95: no Fortran 77 compiler found
customize PGroupFCompiler
Could not locate executable pgfortran
pg: no Fortran 77 compiler found
Found executable /usr/bin/libtool
pg: no Fortran 77 compiler found
don't know how to compile Fortran code on platform 'posix'
warning: build_ext: f77_compiler=None is not available.

building 'sieve' extension
error: extension 'sieve' has Fortran sources but no Fortran compiler found
Das ist die gleiche Fehlermeldung.
Kontrapaganda
User
Beiträge: 7
Registriert: Mittwoch 14. August 2019, 18:25

Montag 9. Dezember 2019, 14:30

Ich habe mittlerweile Python 3.8, NumPy und auch den Intel Fortran Compiler neu installiert. Jetzt läuft es.
Ich habe es auch schon geschafft, ein banales Test-Skript zum Laufen zu bekommen.
Doch, was jetzt als Fehler auftritt, ist noch viel schräger, als alles vorherige.

Ein Array soll als Input-Argument eingelesen werden. Die Dimension wird als weiteres Input-Argument gleich mitgegeben.
Beim Ausführen gibt es folgenden Error:

Code: Alles auswählen

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
sieve.error: (len(x_arr_int)>=n_num) failed for 1st keyword n_num: sieve:n_num=51
Laut dieser Meldung passt das Integer-Input-Argument „n_num˝ nicht zur Länge von „x_arr_int˝. Es müsste = 15 sein. Laut Fehlermeldung ist es hingegen = 51.
Das Problem daran ist, dass diese Aussage schlicht und ergreifend falsch ist. Das eingegebene Argument „n_num˝ ist eigentlich wirklich = 15.
Ein Test mit 19 führte zu 83.

Merkwürdigerweise löst sich das Probelm dadurch, dass ich beim Definieren der Input-Arrays den Doppelpunkt setze. Dadurch alloziert er die Arrays automatisch anhand der Input-Arrays.
Bei meinem Testskript davor ergab sich dieses Probelm nicht. Dort hatte ich die Array-Length als Input-Integer explizit angegeben. Es gab keine Probleme damit.
Deshalb hatte ich überhaupt die Array-Length explizit angegeben. Rätselhaft
Benutzeravatar
__blackjack__
User
Beiträge: 4905
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Montag 9. Dezember 2019, 16:34

@Kontrapaganda: Vielleicht macht das ja Sinn für einen Fortran-Programmierer was Du da schreibst, denn ich verstehe nur Bahnhof, aber ich bin mir fast sicher auch ein Fortran-Programmierer würde an der Stelle ganz gerne mal sehen was Du da eigentlich genau machst. Wir kennen hier ja weder den Python- noch den Fortran-Code der zu dieser Ausnahme führt.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Kontrapaganda
User
Beiträge: 7
Registriert: Mittwoch 14. August 2019, 18:25

Montag 9. Dezember 2019, 21:40

Ach so, tut mir leid. ich hatte den Code bisher noch nicht gepostet, da das ursprüngliche Problem ja nichts mit einem konkreten Anwendungsfall zu tun hatte.
Die komische Festellung, von der ich schrieb, hat in der Tat mehr mit Fortran zu tun als mit Python. Es gehört hier vielleicht gar nicht rein.

Das Skript soll ein Array von ungeraden zahlen auf die Teilbarkeit durch alle Primzahlen bis zu deren abgerundeter Wurzel testen, um kontinuierlich eine Primzahlliste zu bauen.
Das hatte ich bisher mit NumPy und dem kartesischen Produkt gelöst. Eine Interpretationsfunktion setzt mittels np.where() anschließend eine Null für die Teilbarkeit mit Rest und eine 1 für die restlose Teilbarkeit.
Durch spaltenweises Summieren mittels np.matmul() erkennt man nun Primzahlen anhand der 0 als Summe. Das ist algorithmisch gesehen ineffizient, da die meisten Zahlen bereits durch kleine Primzahlen geteilt werden, sodass sehr viele unnötige Divisonen durchgeführt werden. Die Alternative wären Python-Loops gewesen, doch über deren Performance braucht man nicht viel zu sagen.
Ein weiteres Problem war, dass ich nicht immer vollständige Primquadratintervalle benutzen konnte, da irgendwann die Primzahllücken zu groß werden und es in Verbindung mit dem kartesischen Produkt bei etwa 2+e08 zum Memory-Error kommt. Zudem bremst das ständige Lesen und Schreiben in den RAM großer Datenmengen unnötig. Der Fortran-Loop löst dieses Probelm, da er kaum RAM braucht und schneller ist.

Code: Alles auswählen

import numpy as np
import os as os
import sieve

x_max = int(input('Insert range to compute prime list up to:'))
x_root = int(2 * np.floor((1 + np.sqrt(x_max)) / 2)) - 1
prm_def = 0
x_stop = -1
x_oddsq0 = pow(np.linspace(1, x_root+2, int((x_root+3)/2)), 2).astype(int)
z_oddsq0 = np.zeros(int((x_root+3)/2))
xrs = pow(x_root+2, 2)
prime_list = np.zeros(int(np.divide(xrs, np.log(xrs))*1.2)).astype(int)
prime_list[:] = 2 * xrs
prime_list[0] = 2
prm_sum = 1

def f_i(a, b):
    #return (np.floor(a/b) - np.ceil(a/b) + 1)
    return (np.where(np.floor(a/b) == a/b, 1, 0))
    #return (np.where((a % b) == 0, 1, 0))

#def f_z0(a):
    #return (np.where(pdiv_sum == prm_def, 1, 0))
    #return ((np.absolute(a+1-prm_def) + np.absolute(a-1-prm_def) - 2*np.absolute(a-prm_def)) / 2)

for xr_tmp in range(1, x_root+1, 2):
    x_start = x_stop + 4
    x_stop = x_start + 4 * xr_tmp
    primelist_tmp = prime_list[np.where(prime_list <= xr_tmp)[0]]
    prm_sum_tmp = np.sum(primelist_tmp * 0 + 1)

#    x_arr = (np.linspace(x_start, x_stop, 2*xr_tmp+1)
#             .reshape(2*xr_tmp+1, 1))    
#    prmic = f_i(x_arr, primelist_tmp)
#    mtp = np.ones(prm_sum_tmp).reshape(prm_sum_tmp, 1)
#    pdiv_sum = np.matmul(prmic, mtp)[:, 0]

    x_arr = np.linspace(x_start, x_stop, 2*xr_tmp+1)
    pdiv_sum = sieve.sieve(2*xr_tmp+1, prm_sum_tmp, x_arr, primelist_tmp)

    primelist_new = (np.where(pdiv_sum == prm_def))[0] * 2 + x_start
    prm_sum_new = len(primelist_new)
    prime_list[prm_sum : prm_sum + prm_sum_new] = primelist_new
    print(xr_tmp)
    #print('Prime list is completed from 0 to', x_stop, '.')
    prm_sum += prm_sum_new
    z_oddsq0[int((xr_tmp+1)/2)] = prm_sum

z_oddsq0 = z_oddsq0.astype(int)
prime_list = prime_list.copy()[np.where(prime_list != 2*xrs)[0]]
prm_sum = len(prime_list)
prime_list = np.array(prime_list.copy(), int)
prime_list[0] = 2
prm_num = len(prime_list)
func_zeta = np.array(np.linspace(0, 0, x_stop+3), int)
func_zeta[prime_list] = 1
print("There're", prm_num, "primes.")

print('Restoring prime list to disk...')
np.save(f'./prime_list_{pow(x_root+2, 2)}.npy', prime_list)
print('Restoring prime list to disk has been completed.')

#print('Restoring uncumulated zeta function to disk...')
#np.savetxt('./../arrays.d/func_zeta.txt', func_zeta)
#print('Restoring uncumulated zeta function to disk is completed.')

#exec(open('./zf_cum_exact.py').read())

pl = prime_list[np.where(prime_list <= x_max)[0]]
print("There're", sum(prime_list*0+1), "primes from", 1, "to",
      pow(x_root+2, 2), ".")

Code: Alles auswählen


subroutine sieve(n_num, prm_sum_tmp, x_arr_int, primelist_tmp, pdiv_sum)
  implicit none
  
  integer(kind=8), intent(in) :: n_num
  integer(kind=8), intent(in) :: prm_sum_tmp
  integer(kind=8), intent(in) :: x_arr_int(:)
  integer(kind=8), intent(in) :: primelist_tmp(:)
  integer(kind=8), intent(out) :: pdiv_sum(n_num)
  integer(kind=8) :: i, j
  real(kind=8) :: x_arr_float(n_num)
  
!  write(*,*) "n_num =", n_num
  x_arr_float = real(x_arr_int)
  pdiv_sum(:) = 1

  do i = 1, n_num, 1
	do j = 2, prm_sum_tmp, 1
	  if ((x_arr_int(i) / primelist_tmp(j)) == (x_arr_float(i) / primelist_tmp(j))) then
		goto 10
	  end if
	end do
	
	pdiv_sum(i) = 0	
10	continue
end do
  
end subroutine sieve
Antworten