Reducing the size of scipy and numpy for aws lambda deployment
I am trying to deploy a python application on aws lambda. It has several large python dependencies, the largest being scipy and numpy. The result is that my application is significantly larger than the allowed 250MB.
While trying to find a way to reduce the size, I came across the approach detailed here:
https://github.com/szelenka/shrink-linalg
In essence, when installing using pip, during the scipy & numpy cython compilation, flags can be passed to the c compiler that will leave out the debugging information in the compiled c binaries. The result is that scipy and numpy are reduced to about 50% of the original size. I was able to run this locally (ubuntu 16.04) , and created the binaries without issue. The command used was:
CFLAGS="-g0 -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib" pip install numpy scipy --compile --no-cache-dir --global-option=build_ext --global-option="-j 4"
The problem is that in order to run on aws lambda, the binaries must be compiled in a similar environment to the one lambda runs on. An image of the environment can be found here:
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
After loading the image on an ec2 instance, I tried to run the same pip installation after installing a few dependencies
sudo yum install python36 python3-devel blas-devel atlas atlas-devel lapack-devel atlas-sse3-devel gcc gcc-64 gcc-gfortran gcc64-gfortran libgfortran, gcc-c++ openblas-devel python36-virtualenv
The numpy is compiling fine, but scipy is not. The cython is not causing any problems, but the fortran compilation is. I am getting the following error:
error: Command "/usr/bin/gfortran -Wall -g -Wall -g -shared build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_bandedmodule.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/fortranobject.o build/temp.linux-x86_64-3.6/scipy/integrate/tests/banded5x5.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded-f2pywrappers.o -L/usr/lib64/atlas -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib64 -Lbuild/temp.linux-x86_64-3.6 -llsoda -lmach -llapack -lptf77blas -lptcblas -latlas -lptf77blas -lptcblas -lpython3.6m -lgfortran -o build/lib.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded.cpython-36m-x86_64-linux-gnu.so -Wl,--version-script=build/temp.linux-x86_64-3.6/link-version-scipy.integrate._test_odeint_banded.map" failed with exit status 1
I have tried re-installing gfortran as well as the whole gcc collection, but without any luck. Unfortunately, I have very limited experience with fortran compilers. If anyone has any ideas, or has a compiled version of the c binaries, I'd be quite grateful.
amazon-web-services scipy aws-lambda cython gfortran
add a comment |
I am trying to deploy a python application on aws lambda. It has several large python dependencies, the largest being scipy and numpy. The result is that my application is significantly larger than the allowed 250MB.
While trying to find a way to reduce the size, I came across the approach detailed here:
https://github.com/szelenka/shrink-linalg
In essence, when installing using pip, during the scipy & numpy cython compilation, flags can be passed to the c compiler that will leave out the debugging information in the compiled c binaries. The result is that scipy and numpy are reduced to about 50% of the original size. I was able to run this locally (ubuntu 16.04) , and created the binaries without issue. The command used was:
CFLAGS="-g0 -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib" pip install numpy scipy --compile --no-cache-dir --global-option=build_ext --global-option="-j 4"
The problem is that in order to run on aws lambda, the binaries must be compiled in a similar environment to the one lambda runs on. An image of the environment can be found here:
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
After loading the image on an ec2 instance, I tried to run the same pip installation after installing a few dependencies
sudo yum install python36 python3-devel blas-devel atlas atlas-devel lapack-devel atlas-sse3-devel gcc gcc-64 gcc-gfortran gcc64-gfortran libgfortran, gcc-c++ openblas-devel python36-virtualenv
The numpy is compiling fine, but scipy is not. The cython is not causing any problems, but the fortran compilation is. I am getting the following error:
error: Command "/usr/bin/gfortran -Wall -g -Wall -g -shared build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_bandedmodule.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/fortranobject.o build/temp.linux-x86_64-3.6/scipy/integrate/tests/banded5x5.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded-f2pywrappers.o -L/usr/lib64/atlas -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib64 -Lbuild/temp.linux-x86_64-3.6 -llsoda -lmach -llapack -lptf77blas -lptcblas -latlas -lptf77blas -lptcblas -lpython3.6m -lgfortran -o build/lib.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded.cpython-36m-x86_64-linux-gnu.so -Wl,--version-script=build/temp.linux-x86_64-3.6/link-version-scipy.integrate._test_odeint_banded.map" failed with exit status 1
I have tried re-installing gfortran as well as the whole gcc collection, but without any luck. Unfortunately, I have very limited experience with fortran compilers. If anyone has any ideas, or has a compiled version of the c binaries, I'd be quite grateful.
amazon-web-services scipy aws-lambda cython gfortran
This is the last (and least informatively) line of the error message... The stuff it tells you first is probably more useful.
– DavidW
Nov 13 '18 at 7:10
Unfortunately, no. Pip's traceback is not very helpful. Before this it just shows all the stuff that compiled successfully
– joek575
Nov 13 '18 at 7:17
1
You might be able to run pip in verbose mode. There almost certainly is more information (even if it's being hidden from you)
– DavidW
Nov 13 '18 at 8:26
Or if there is no verbose mode available, there should be some log file somewhere.
– Vladimir F
Nov 13 '18 at 10:06
add a comment |
I am trying to deploy a python application on aws lambda. It has several large python dependencies, the largest being scipy and numpy. The result is that my application is significantly larger than the allowed 250MB.
While trying to find a way to reduce the size, I came across the approach detailed here:
https://github.com/szelenka/shrink-linalg
In essence, when installing using pip, during the scipy & numpy cython compilation, flags can be passed to the c compiler that will leave out the debugging information in the compiled c binaries. The result is that scipy and numpy are reduced to about 50% of the original size. I was able to run this locally (ubuntu 16.04) , and created the binaries without issue. The command used was:
CFLAGS="-g0 -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib" pip install numpy scipy --compile --no-cache-dir --global-option=build_ext --global-option="-j 4"
The problem is that in order to run on aws lambda, the binaries must be compiled in a similar environment to the one lambda runs on. An image of the environment can be found here:
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
After loading the image on an ec2 instance, I tried to run the same pip installation after installing a few dependencies
sudo yum install python36 python3-devel blas-devel atlas atlas-devel lapack-devel atlas-sse3-devel gcc gcc-64 gcc-gfortran gcc64-gfortran libgfortran, gcc-c++ openblas-devel python36-virtualenv
The numpy is compiling fine, but scipy is not. The cython is not causing any problems, but the fortran compilation is. I am getting the following error:
error: Command "/usr/bin/gfortran -Wall -g -Wall -g -shared build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_bandedmodule.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/fortranobject.o build/temp.linux-x86_64-3.6/scipy/integrate/tests/banded5x5.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded-f2pywrappers.o -L/usr/lib64/atlas -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib64 -Lbuild/temp.linux-x86_64-3.6 -llsoda -lmach -llapack -lptf77blas -lptcblas -latlas -lptf77blas -lptcblas -lpython3.6m -lgfortran -o build/lib.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded.cpython-36m-x86_64-linux-gnu.so -Wl,--version-script=build/temp.linux-x86_64-3.6/link-version-scipy.integrate._test_odeint_banded.map" failed with exit status 1
I have tried re-installing gfortran as well as the whole gcc collection, but without any luck. Unfortunately, I have very limited experience with fortran compilers. If anyone has any ideas, or has a compiled version of the c binaries, I'd be quite grateful.
amazon-web-services scipy aws-lambda cython gfortran
I am trying to deploy a python application on aws lambda. It has several large python dependencies, the largest being scipy and numpy. The result is that my application is significantly larger than the allowed 250MB.
While trying to find a way to reduce the size, I came across the approach detailed here:
https://github.com/szelenka/shrink-linalg
In essence, when installing using pip, during the scipy & numpy cython compilation, flags can be passed to the c compiler that will leave out the debugging information in the compiled c binaries. The result is that scipy and numpy are reduced to about 50% of the original size. I was able to run this locally (ubuntu 16.04) , and created the binaries without issue. The command used was:
CFLAGS="-g0 -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib" pip install numpy scipy --compile --no-cache-dir --global-option=build_ext --global-option="-j 4"
The problem is that in order to run on aws lambda, the binaries must be compiled in a similar environment to the one lambda runs on. An image of the environment can be found here:
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html
After loading the image on an ec2 instance, I tried to run the same pip installation after installing a few dependencies
sudo yum install python36 python3-devel blas-devel atlas atlas-devel lapack-devel atlas-sse3-devel gcc gcc-64 gcc-gfortran gcc64-gfortran libgfortran, gcc-c++ openblas-devel python36-virtualenv
The numpy is compiling fine, but scipy is not. The cython is not causing any problems, but the fortran compilation is. I am getting the following error:
error: Command "/usr/bin/gfortran -Wall -g -Wall -g -shared build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_bandedmodule.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/fortranobject.o build/temp.linux-x86_64-3.6/scipy/integrate/tests/banded5x5.o build/temp.linux-x86_64-3.6/build/src.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded-f2pywrappers.o -L/usr/lib64/atlas -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib/gcc/x86_64-amazon-linux/6.4.1 -L/usr/lib64 -Lbuild/temp.linux-x86_64-3.6 -llsoda -lmach -llapack -lptf77blas -lptcblas -latlas -lptf77blas -lptcblas -lpython3.6m -lgfortran -o build/lib.linux-x86_64-3.6/scipy/integrate/_test_odeint_banded.cpython-36m-x86_64-linux-gnu.so -Wl,--version-script=build/temp.linux-x86_64-3.6/link-version-scipy.integrate._test_odeint_banded.map" failed with exit status 1
I have tried re-installing gfortran as well as the whole gcc collection, but without any luck. Unfortunately, I have very limited experience with fortran compilers. If anyone has any ideas, or has a compiled version of the c binaries, I'd be quite grateful.
amazon-web-services scipy aws-lambda cython gfortran
amazon-web-services scipy aws-lambda cython gfortran
edited Nov 13 '18 at 9:06
albert
2,79731123
2,79731123
asked Nov 13 '18 at 5:18
joek575
215
215
This is the last (and least informatively) line of the error message... The stuff it tells you first is probably more useful.
– DavidW
Nov 13 '18 at 7:10
Unfortunately, no. Pip's traceback is not very helpful. Before this it just shows all the stuff that compiled successfully
– joek575
Nov 13 '18 at 7:17
1
You might be able to run pip in verbose mode. There almost certainly is more information (even if it's being hidden from you)
– DavidW
Nov 13 '18 at 8:26
Or if there is no verbose mode available, there should be some log file somewhere.
– Vladimir F
Nov 13 '18 at 10:06
add a comment |
This is the last (and least informatively) line of the error message... The stuff it tells you first is probably more useful.
– DavidW
Nov 13 '18 at 7:10
Unfortunately, no. Pip's traceback is not very helpful. Before this it just shows all the stuff that compiled successfully
– joek575
Nov 13 '18 at 7:17
1
You might be able to run pip in verbose mode. There almost certainly is more information (even if it's being hidden from you)
– DavidW
Nov 13 '18 at 8:26
Or if there is no verbose mode available, there should be some log file somewhere.
– Vladimir F
Nov 13 '18 at 10:06
This is the last (and least informatively) line of the error message... The stuff it tells you first is probably more useful.
– DavidW
Nov 13 '18 at 7:10
This is the last (and least informatively) line of the error message... The stuff it tells you first is probably more useful.
– DavidW
Nov 13 '18 at 7:10
Unfortunately, no. Pip's traceback is not very helpful. Before this it just shows all the stuff that compiled successfully
– joek575
Nov 13 '18 at 7:17
Unfortunately, no. Pip's traceback is not very helpful. Before this it just shows all the stuff that compiled successfully
– joek575
Nov 13 '18 at 7:17
1
1
You might be able to run pip in verbose mode. There almost certainly is more information (even if it's being hidden from you)
– DavidW
Nov 13 '18 at 8:26
You might be able to run pip in verbose mode. There almost certainly is more information (even if it's being hidden from you)
– DavidW
Nov 13 '18 at 8:26
Or if there is no verbose mode available, there should be some log file somewhere.
– Vladimir F
Nov 13 '18 at 10:06
Or if there is no verbose mode available, there should be some log file somewhere.
– Vladimir F
Nov 13 '18 at 10:06
add a comment |
1 Answer
1
active
oldest
votes
Ok, so, i solved this, albeit in a pretty hacky way.
The flags i was passing to pip were meant to reduce the size of the c dependencies, not the fortran dependencies. So there was really no problem using the precompiled fortran dependencies that are normally downloaded via pip.
So first i created a reference version of the unaltered scipy package in a folder sp:
pip install scipy -t sp
I then created a go program to act as a wrapper around the gfortran compiler (or technically around the link to the gfortran compiler in /usr/bin)
package main
import "os"
import "strings"
import "io/ioutil"
import "log"
import "os/exec"
import "fmt"
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { return true, nil }
if os.IsNotExist(err) { return false, nil }
return true, err
}
func copyr(src string, dst string) {
// Read all content of src to data
data, err := ioutil.ReadFile(src)
checkErr(err)
// Write data to dst
err = ioutil.WriteFile(dst, data, 0644)
checkErr(err)
}
func main() {
search_folder := "/home/ec2-user/sp/scipy"
wrapped_compiler := "/usr/bin/inner_gfortran"
argsWithProg := os.Args
noProg := os.Args[1:]
primed := 0
check := "-o"
var (
cmdOut byte
err error
)
for _, el := range argsWithProg {
if primed == 1{
primed = 0
s := strings.Split(el, "scipy")
if len(s) != 2{
continue
}
src := search_folder + s[1]
src_exi, _ := exists(src)
if src_exi == false {
continue
}
primed = 2
dir_parts := strings.Split(el, "/")
dir_parts = dir_parts[:len(dir_parts)-1]
dir := strings.Join(dir_parts,"/")
exi, _ := exists(dir)
if exi == false {
os.MkdirAll(dir, os.ModePerm)
}
os.Create(el)
copyr(src, el)
}
if el == check{
primed = 1
}
}
if primed == 0 {
if cmdOut, err = exec.Command(wrapped_compiler, noProg...).Output(); err != nil {
fmt.Fprintln(os.Stderr, "There was an error running fortran compiler: ", err)
os.Exit(1)
}
os.Stdout.Write(cmdOut)
}
}
Moved the actual compiler to inner_gfortran
sudo mv /usr/bin/gfortran /usr/bin/inner_gfortran
And put the go wrapper in its place
The wrapper will pass most instructions on to the compiler, but if the instruction is to compile a fortran program to scipy, and the compiled binary already exists in my reference version of scipy, the wrapper simply copies the reference version into the new version being compiled.
And that did it. The reduced size versions of scipy and numpy now work on aws lambda for python 3.6.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53274271%2freducing-the-size-of-scipy-and-numpy-for-aws-lambda-deployment%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Ok, so, i solved this, albeit in a pretty hacky way.
The flags i was passing to pip were meant to reduce the size of the c dependencies, not the fortran dependencies. So there was really no problem using the precompiled fortran dependencies that are normally downloaded via pip.
So first i created a reference version of the unaltered scipy package in a folder sp:
pip install scipy -t sp
I then created a go program to act as a wrapper around the gfortran compiler (or technically around the link to the gfortran compiler in /usr/bin)
package main
import "os"
import "strings"
import "io/ioutil"
import "log"
import "os/exec"
import "fmt"
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { return true, nil }
if os.IsNotExist(err) { return false, nil }
return true, err
}
func copyr(src string, dst string) {
// Read all content of src to data
data, err := ioutil.ReadFile(src)
checkErr(err)
// Write data to dst
err = ioutil.WriteFile(dst, data, 0644)
checkErr(err)
}
func main() {
search_folder := "/home/ec2-user/sp/scipy"
wrapped_compiler := "/usr/bin/inner_gfortran"
argsWithProg := os.Args
noProg := os.Args[1:]
primed := 0
check := "-o"
var (
cmdOut byte
err error
)
for _, el := range argsWithProg {
if primed == 1{
primed = 0
s := strings.Split(el, "scipy")
if len(s) != 2{
continue
}
src := search_folder + s[1]
src_exi, _ := exists(src)
if src_exi == false {
continue
}
primed = 2
dir_parts := strings.Split(el, "/")
dir_parts = dir_parts[:len(dir_parts)-1]
dir := strings.Join(dir_parts,"/")
exi, _ := exists(dir)
if exi == false {
os.MkdirAll(dir, os.ModePerm)
}
os.Create(el)
copyr(src, el)
}
if el == check{
primed = 1
}
}
if primed == 0 {
if cmdOut, err = exec.Command(wrapped_compiler, noProg...).Output(); err != nil {
fmt.Fprintln(os.Stderr, "There was an error running fortran compiler: ", err)
os.Exit(1)
}
os.Stdout.Write(cmdOut)
}
}
Moved the actual compiler to inner_gfortran
sudo mv /usr/bin/gfortran /usr/bin/inner_gfortran
And put the go wrapper in its place
The wrapper will pass most instructions on to the compiler, but if the instruction is to compile a fortran program to scipy, and the compiled binary already exists in my reference version of scipy, the wrapper simply copies the reference version into the new version being compiled.
And that did it. The reduced size versions of scipy and numpy now work on aws lambda for python 3.6.
add a comment |
Ok, so, i solved this, albeit in a pretty hacky way.
The flags i was passing to pip were meant to reduce the size of the c dependencies, not the fortran dependencies. So there was really no problem using the precompiled fortran dependencies that are normally downloaded via pip.
So first i created a reference version of the unaltered scipy package in a folder sp:
pip install scipy -t sp
I then created a go program to act as a wrapper around the gfortran compiler (or technically around the link to the gfortran compiler in /usr/bin)
package main
import "os"
import "strings"
import "io/ioutil"
import "log"
import "os/exec"
import "fmt"
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { return true, nil }
if os.IsNotExist(err) { return false, nil }
return true, err
}
func copyr(src string, dst string) {
// Read all content of src to data
data, err := ioutil.ReadFile(src)
checkErr(err)
// Write data to dst
err = ioutil.WriteFile(dst, data, 0644)
checkErr(err)
}
func main() {
search_folder := "/home/ec2-user/sp/scipy"
wrapped_compiler := "/usr/bin/inner_gfortran"
argsWithProg := os.Args
noProg := os.Args[1:]
primed := 0
check := "-o"
var (
cmdOut byte
err error
)
for _, el := range argsWithProg {
if primed == 1{
primed = 0
s := strings.Split(el, "scipy")
if len(s) != 2{
continue
}
src := search_folder + s[1]
src_exi, _ := exists(src)
if src_exi == false {
continue
}
primed = 2
dir_parts := strings.Split(el, "/")
dir_parts = dir_parts[:len(dir_parts)-1]
dir := strings.Join(dir_parts,"/")
exi, _ := exists(dir)
if exi == false {
os.MkdirAll(dir, os.ModePerm)
}
os.Create(el)
copyr(src, el)
}
if el == check{
primed = 1
}
}
if primed == 0 {
if cmdOut, err = exec.Command(wrapped_compiler, noProg...).Output(); err != nil {
fmt.Fprintln(os.Stderr, "There was an error running fortran compiler: ", err)
os.Exit(1)
}
os.Stdout.Write(cmdOut)
}
}
Moved the actual compiler to inner_gfortran
sudo mv /usr/bin/gfortran /usr/bin/inner_gfortran
And put the go wrapper in its place
The wrapper will pass most instructions on to the compiler, but if the instruction is to compile a fortran program to scipy, and the compiled binary already exists in my reference version of scipy, the wrapper simply copies the reference version into the new version being compiled.
And that did it. The reduced size versions of scipy and numpy now work on aws lambda for python 3.6.
add a comment |
Ok, so, i solved this, albeit in a pretty hacky way.
The flags i was passing to pip were meant to reduce the size of the c dependencies, not the fortran dependencies. So there was really no problem using the precompiled fortran dependencies that are normally downloaded via pip.
So first i created a reference version of the unaltered scipy package in a folder sp:
pip install scipy -t sp
I then created a go program to act as a wrapper around the gfortran compiler (or technically around the link to the gfortran compiler in /usr/bin)
package main
import "os"
import "strings"
import "io/ioutil"
import "log"
import "os/exec"
import "fmt"
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { return true, nil }
if os.IsNotExist(err) { return false, nil }
return true, err
}
func copyr(src string, dst string) {
// Read all content of src to data
data, err := ioutil.ReadFile(src)
checkErr(err)
// Write data to dst
err = ioutil.WriteFile(dst, data, 0644)
checkErr(err)
}
func main() {
search_folder := "/home/ec2-user/sp/scipy"
wrapped_compiler := "/usr/bin/inner_gfortran"
argsWithProg := os.Args
noProg := os.Args[1:]
primed := 0
check := "-o"
var (
cmdOut byte
err error
)
for _, el := range argsWithProg {
if primed == 1{
primed = 0
s := strings.Split(el, "scipy")
if len(s) != 2{
continue
}
src := search_folder + s[1]
src_exi, _ := exists(src)
if src_exi == false {
continue
}
primed = 2
dir_parts := strings.Split(el, "/")
dir_parts = dir_parts[:len(dir_parts)-1]
dir := strings.Join(dir_parts,"/")
exi, _ := exists(dir)
if exi == false {
os.MkdirAll(dir, os.ModePerm)
}
os.Create(el)
copyr(src, el)
}
if el == check{
primed = 1
}
}
if primed == 0 {
if cmdOut, err = exec.Command(wrapped_compiler, noProg...).Output(); err != nil {
fmt.Fprintln(os.Stderr, "There was an error running fortran compiler: ", err)
os.Exit(1)
}
os.Stdout.Write(cmdOut)
}
}
Moved the actual compiler to inner_gfortran
sudo mv /usr/bin/gfortran /usr/bin/inner_gfortran
And put the go wrapper in its place
The wrapper will pass most instructions on to the compiler, but if the instruction is to compile a fortran program to scipy, and the compiled binary already exists in my reference version of scipy, the wrapper simply copies the reference version into the new version being compiled.
And that did it. The reduced size versions of scipy and numpy now work on aws lambda for python 3.6.
Ok, so, i solved this, albeit in a pretty hacky way.
The flags i was passing to pip were meant to reduce the size of the c dependencies, not the fortran dependencies. So there was really no problem using the precompiled fortran dependencies that are normally downloaded via pip.
So first i created a reference version of the unaltered scipy package in a folder sp:
pip install scipy -t sp
I then created a go program to act as a wrapper around the gfortran compiler (or technically around the link to the gfortran compiler in /usr/bin)
package main
import "os"
import "strings"
import "io/ioutil"
import "log"
import "os/exec"
import "fmt"
func checkErr(err error) {
if err != nil {
log.Fatal(err)
}
}
func exists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil { return true, nil }
if os.IsNotExist(err) { return false, nil }
return true, err
}
func copyr(src string, dst string) {
// Read all content of src to data
data, err := ioutil.ReadFile(src)
checkErr(err)
// Write data to dst
err = ioutil.WriteFile(dst, data, 0644)
checkErr(err)
}
func main() {
search_folder := "/home/ec2-user/sp/scipy"
wrapped_compiler := "/usr/bin/inner_gfortran"
argsWithProg := os.Args
noProg := os.Args[1:]
primed := 0
check := "-o"
var (
cmdOut byte
err error
)
for _, el := range argsWithProg {
if primed == 1{
primed = 0
s := strings.Split(el, "scipy")
if len(s) != 2{
continue
}
src := search_folder + s[1]
src_exi, _ := exists(src)
if src_exi == false {
continue
}
primed = 2
dir_parts := strings.Split(el, "/")
dir_parts = dir_parts[:len(dir_parts)-1]
dir := strings.Join(dir_parts,"/")
exi, _ := exists(dir)
if exi == false {
os.MkdirAll(dir, os.ModePerm)
}
os.Create(el)
copyr(src, el)
}
if el == check{
primed = 1
}
}
if primed == 0 {
if cmdOut, err = exec.Command(wrapped_compiler, noProg...).Output(); err != nil {
fmt.Fprintln(os.Stderr, "There was an error running fortran compiler: ", err)
os.Exit(1)
}
os.Stdout.Write(cmdOut)
}
}
Moved the actual compiler to inner_gfortran
sudo mv /usr/bin/gfortran /usr/bin/inner_gfortran
And put the go wrapper in its place
The wrapper will pass most instructions on to the compiler, but if the instruction is to compile a fortran program to scipy, and the compiled binary already exists in my reference version of scipy, the wrapper simply copies the reference version into the new version being compiled.
And that did it. The reduced size versions of scipy and numpy now work on aws lambda for python 3.6.
edited Nov 13 '18 at 22:10
answered Nov 13 '18 at 19:39
joek575
215
215
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53274271%2freducing-the-size-of-scipy-and-numpy-for-aws-lambda-deployment%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
This is the last (and least informatively) line of the error message... The stuff it tells you first is probably more useful.
– DavidW
Nov 13 '18 at 7:10
Unfortunately, no. Pip's traceback is not very helpful. Before this it just shows all the stuff that compiled successfully
– joek575
Nov 13 '18 at 7:17
1
You might be able to run pip in verbose mode. There almost certainly is more information (even if it's being hidden from you)
– DavidW
Nov 13 '18 at 8:26
Or if there is no verbose mode available, there should be some log file somewhere.
– Vladimir F
Nov 13 '18 at 10:06