简体   繁体   中英

Error using scipy.weave.inline

I am using several techniques ( NumPy , Weave , Cython , Numba ) to perform a Python performance benchmark. The code takes two numpy arrays of size NxN and multiplies them element-wise and stores the values in another array C.

My weave.inline() code gives me a scipy.weave.build_tools.CompileError . I have created a minimalist piece of code which generates the same error. Could someone please help?

import time

import numpy as np
from scipy import weave
from scipy.weave import converters


def benchmark():

    N = np.array(5000, dtype=np.int)

    A = np.random.rand(N, N)
    B = np.random.rand(N, N)
    C = np.zeros([N, N], dtype=float)

    t = time.clock()
    weave_inline_loop(A, B, C, N)
    print time.clock() - t


def weave_inline_loop(A, B, C, N):
    code = """
           int i, j;
           for (i = 0; i < N; ++i)
           {
               for (j = 0; j < N; ++j)
               {
                   C(i, j) = A(i, j) * B(i, j);
               }
           }
           return_val = C;
           """
    C = weave.inline(code, ['A', 'B', 'C', 'N'], type_converters=converters.blitz, compiler='gcc')

benchmark()

Two issues. First, you don't need the line return_val = C . You are directly manipulating the data in the variable C in your inlined code, so its already available to python and there's no need to explicitly return it to the environment (and trying to do so is causing errors when trying to do the appropriate type conversions). So change your function to:

def weave_inline_loop(A, B, C, N):
    code = """
           int i, j;
           for (i = 0; i < N; ++i)
           {
               for (j = 0; j < N; ++j)
               {
                   C(i, j) = A(i, j) * B(i, j);
               }
           }
           """
    weave.inline(code, ['A', 'B', 'C', 'N'], type_converters=converters.blitz, compiler='gcc')
    return C

Second issue. You are comparing i and j (both int s), to N an array of length 1. This also generated an error. But if you call your code as:

def benchmark():

    N = np.array(5000, dtype=np.int)

    A = np.random.rand(N, N)
    B = np.random.rand(N, N)
    C = np.zeros([N, N], dtype=float)

    t = time.clock()
    print weave_inline_loop(A, B, C, int(N)) 
    # I added a print statement so you can see that C is being 
    # populated with the new 2d array
    print time.clock() - t

Three small changes are needed:

  • N can't be a 0D-numpy array (it has to be an integer so that i < N works in the C code). You should write N = 5000 instead of N = np.array(5000, dtype=np.int) .

  • The C array is being modified in-place so it doesn't have to be returned. I don't know the restrictions on the kind of objects than return_val can handle, but if you try to keep return_val = C; it fails compiling: don't know how to convert 'blitz::Array<double, 2>' to 'const py::object&' .

  • After that, weave.inline returns None . Keeping the assignment C = weave.inline(... makes the code look confusing, even if it works fine and the array named C will hold the result in the benchmark scope.

This is the end result:

import time
import numpy as np
from scipy import weave
from scipy.weave import converters


def benchmark():
    N = 5000

    A = np.random.rand(N, N)
    B = np.random.rand(N, N)
    C = np.zeros([N, N], dtype=float)

    t = time.clock()
    weave_inline_loop(A, B, C, N)
    print time.clock() - t


def weave_inline_loop(A, B, C, N):
    code = """
           int i, j;
           for (i = 0; i < N; ++i)
           {
               for (j = 0; j < N; ++j)
               {
                   C(i, j) = A(i, j) * B(i, j);
               }
           }
           """
    weave.inline(code, ['A', 'B', 'C', 'N'], type_converters=converters.blitz, compiler='gcc')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM