xref: /oneTBB/python/tbb/test.py (revision 2eccd5f9)
151c0b2f7Stbbdev#!/usr/bin/env python3
251c0b2f7Stbbdev#
3*2eccd5f9SIlya Isaev# Copyright (c) 2016-2022 Intel Corporation
451c0b2f7Stbbdev#
551c0b2f7Stbbdev# Licensed under the Apache License, Version 2.0 (the "License");
651c0b2f7Stbbdev# you may not use this file except in compliance with the License.
751c0b2f7Stbbdev# You may obtain a copy of the License at
851c0b2f7Stbbdev#
951c0b2f7Stbbdev#     http://www.apache.org/licenses/LICENSE-2.0
1051c0b2f7Stbbdev#
1151c0b2f7Stbbdev# Unless required by applicable law or agreed to in writing, software
1251c0b2f7Stbbdev# distributed under the License is distributed on an "AS IS" BASIS,
1351c0b2f7Stbbdev# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1451c0b2f7Stbbdev# See the License for the specific language governing permissions and
1551c0b2f7Stbbdev# limitations under the License.
1651c0b2f7Stbbdev
1751c0b2f7Stbbdev# Based on the software developed by:
1851c0b2f7Stbbdev# Copyright (c) 2008,2016 david decotigny (Pool of threads)
1951c0b2f7Stbbdev# Copyright (c) 2006-2008, R Oudkerk (multiprocessing.Pool)
2051c0b2f7Stbbdev# All rights reserved.
2151c0b2f7Stbbdev#
2251c0b2f7Stbbdev# Redistribution and use in source and binary forms, with or without
2351c0b2f7Stbbdev# modification, are permitted provided that the following conditions
2451c0b2f7Stbbdev# are met:
2551c0b2f7Stbbdev#
2651c0b2f7Stbbdev# 1. Redistributions of source code must retain the above copyright
2751c0b2f7Stbbdev#    notice, this list of conditions and the following disclaimer.
2851c0b2f7Stbbdev# 2. Redistributions in binary form must reproduce the above copyright
2951c0b2f7Stbbdev#    notice, this list of conditions and the following disclaimer in the
3051c0b2f7Stbbdev#    documentation and/or other materials provided with the distribution.
3151c0b2f7Stbbdev# 3. Neither the name of author nor the names of any contributors may be
3251c0b2f7Stbbdev#    used to endorse or promote products derived from this software
3351c0b2f7Stbbdev#    without specific prior written permission.
3451c0b2f7Stbbdev#
3551c0b2f7Stbbdev# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND
3651c0b2f7Stbbdev# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3751c0b2f7Stbbdev# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3851c0b2f7Stbbdev# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
3951c0b2f7Stbbdev# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
4051c0b2f7Stbbdev# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
4151c0b2f7Stbbdev# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
4251c0b2f7Stbbdev# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
4351c0b2f7Stbbdev# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4451c0b2f7Stbbdev# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4551c0b2f7Stbbdev# SUCH DAMAGE.
4651c0b2f7Stbbdev#
4751c0b2f7Stbbdev
4851c0b2f7Stbbdevimport time
4951c0b2f7Stbbdevimport threading
5051c0b2f7Stbbdev
5151c0b2f7Stbbdevfrom .api import *
5251c0b2f7Stbbdevfrom .pool import *
5351c0b2f7Stbbdev
5451c0b2f7Stbbdev
5551c0b2f7Stbbdevdef test(arg=None):
5651c0b2f7Stbbdev    if arg == "-v":
5751c0b2f7Stbbdev        def say(*x):
5851c0b2f7Stbbdev            print(*x)
5951c0b2f7Stbbdev    else:
6051c0b2f7Stbbdev        def say(*x):
6151c0b2f7Stbbdev            pass
6251c0b2f7Stbbdev    say("Start Pool testing")
6351c0b2f7Stbbdev    print("oneTBB version is %s" % runtime_version())
6451c0b2f7Stbbdev    print("oneTBB interface version is %s" % runtime_interface_version())
6551c0b2f7Stbbdev
6651c0b2f7Stbbdev    get_tid = lambda: threading.current_thread().ident
6751c0b2f7Stbbdev
6851c0b2f7Stbbdev    assert default_num_threads() == this_task_arena_max_concurrency()
6951c0b2f7Stbbdev
7051c0b2f7Stbbdev    def return42():
7151c0b2f7Stbbdev        return 42
7251c0b2f7Stbbdev
7351c0b2f7Stbbdev    def f(x):
7451c0b2f7Stbbdev        return x * x
7551c0b2f7Stbbdev
7651c0b2f7Stbbdev    def work(mseconds):
7751c0b2f7Stbbdev        res = str(mseconds)
7851c0b2f7Stbbdev        if mseconds < 0:
7951c0b2f7Stbbdev            mseconds = -mseconds
8051c0b2f7Stbbdev        say("[%d] Start to work for %fms..." % (get_tid(), mseconds*10))
8151c0b2f7Stbbdev        time.sleep(mseconds/100.)
8251c0b2f7Stbbdev        say("[%d] Work done (%fms)." % (get_tid(), mseconds*10))
8351c0b2f7Stbbdev        return res
8451c0b2f7Stbbdev
85*2eccd5f9SIlya Isaev    # special flag to to be set by thread calling async work
86*2eccd5f9SIlya Isaev    spin_flag = None
87*2eccd5f9SIlya Isaev    def timeout_work(param):
88*2eccd5f9SIlya Isaev        say("[%d] Spin wait work start..." % get_tid())
89*2eccd5f9SIlya Isaev        while spin_flag:
90*2eccd5f9SIlya Isaev            time.sleep(0.0001) # yield equivalent
91*2eccd5f9SIlya Isaev        say("[%d] Work done." % get_tid())
92*2eccd5f9SIlya Isaev        return str(param) if param != None else None
93*2eccd5f9SIlya Isaev
94*2eccd5f9SIlya Isaev    def prepare_timeout_exception():
95*2eccd5f9SIlya Isaev        nonlocal spin_flag
96*2eccd5f9SIlya Isaev        spin_flag = True # lock threads in timeout_work
97*2eccd5f9SIlya Isaev
98*2eccd5f9SIlya Isaev    def check_timeout_exception(pool_object, func):
99*2eccd5f9SIlya Isaev        nonlocal spin_flag
100*2eccd5f9SIlya Isaev        try:
101*2eccd5f9SIlya Isaev            func(pool_object)
102*2eccd5f9SIlya Isaev        except TimeoutError:
103*2eccd5f9SIlya Isaev            say("Good. Got expected timeout exception.")
104*2eccd5f9SIlya Isaev        else:
105*2eccd5f9SIlya Isaev            assert False, "Expected exception !"
106*2eccd5f9SIlya Isaev        spin_flag = False # unlock threads in timeout_work
107*2eccd5f9SIlya Isaev
10851c0b2f7Stbbdev    ### Test copy/pasted from multiprocessing
10951c0b2f7Stbbdev    pool = Pool(4)  # start worker threads
11051c0b2f7Stbbdev
11151c0b2f7Stbbdev    # edge cases
11251c0b2f7Stbbdev    assert pool.map(return42, []) == []
11351c0b2f7Stbbdev    assert pool.apply_async(return42, []).get() == 42
11451c0b2f7Stbbdev    assert pool.apply(return42, []) == 42
11551c0b2f7Stbbdev    assert list(pool.imap(return42, iter([]))) == []
11651c0b2f7Stbbdev    assert list(pool.imap_unordered(return42, iter([]))) == []
11751c0b2f7Stbbdev    assert pool.map_async(return42, []).get() == []
11851c0b2f7Stbbdev    assert list(pool.imap_async(return42, iter([])).get()) == []
11951c0b2f7Stbbdev    assert list(pool.imap_unordered_async(return42, iter([])).get()) == []
12051c0b2f7Stbbdev
12151c0b2f7Stbbdev    # basic tests
12251c0b2f7Stbbdev    result = pool.apply_async(f, (10,))  # evaluate "f(10)" asynchronously
12351c0b2f7Stbbdev    assert result.get(timeout=1) == 100  # ... unless slow computer
12451c0b2f7Stbbdev    assert list(pool.map(f, range(10))) == list(map(f, range(10)))
12551c0b2f7Stbbdev    it = pool.imap(f, range(10))
12651c0b2f7Stbbdev    assert next(it) == 0
12751c0b2f7Stbbdev    assert next(it) == 1
12851c0b2f7Stbbdev    assert next(it) == 4
12951c0b2f7Stbbdev
13051c0b2f7Stbbdev    # Test apply_sync exceptions
131*2eccd5f9SIlya Isaev    prepare_timeout_exception()
132*2eccd5f9SIlya Isaev    result = pool.apply_async(timeout_work, (None,))
133*2eccd5f9SIlya Isaev    check_timeout_exception(result, lambda result : say(result.get(timeout=1)))
13451c0b2f7Stbbdev    assert result.get() is None  # sleep() returns None
13551c0b2f7Stbbdev
13651c0b2f7Stbbdev    def cb(s):
13751c0b2f7Stbbdev        say("Result ready: %s" % s)
13851c0b2f7Stbbdev
13951c0b2f7Stbbdev    # Test imap()
14051c0b2f7Stbbdev    assert list(pool.imap(work, range(10, 3, -1), chunksize=4)) == list(map(
14151c0b2f7Stbbdev        str, range(10, 3, -1)))
14251c0b2f7Stbbdev
14351c0b2f7Stbbdev    # Test imap_unordered()
14451c0b2f7Stbbdev    assert sorted(pool.imap_unordered(work, range(10, 3, -1))) == sorted(map(
14551c0b2f7Stbbdev        str, range(10, 3, -1)))
14651c0b2f7Stbbdev
14751c0b2f7Stbbdev    # Test map_async()
148*2eccd5f9SIlya Isaev    prepare_timeout_exception()
149*2eccd5f9SIlya Isaev    result = pool.map_async(timeout_work, range(10), callback=cb)
150*2eccd5f9SIlya Isaev    check_timeout_exception(result, lambda result : result.get(timeout=0.01))
15151c0b2f7Stbbdev    say(result.get())
15251c0b2f7Stbbdev
15351c0b2f7Stbbdev    # Test imap_async()
154*2eccd5f9SIlya Isaev    prepare_timeout_exception()
155*2eccd5f9SIlya Isaev    result = pool.imap_async(timeout_work, range(3, 10), callback=cb)
156*2eccd5f9SIlya Isaev    check_timeout_exception(result, lambda result : result.get(timeout=0.01))
15751c0b2f7Stbbdev    for i in result.get():
15851c0b2f7Stbbdev        say("Item:", i)
15951c0b2f7Stbbdev    say("### Loop again:")
16051c0b2f7Stbbdev    for i in result.get():
16151c0b2f7Stbbdev        say("Item2:", i)
16251c0b2f7Stbbdev
16351c0b2f7Stbbdev    # Test imap_unordered_async()
164*2eccd5f9SIlya Isaev    prepare_timeout_exception()
165*2eccd5f9SIlya Isaev    result = pool.imap_unordered_async(timeout_work, range(10, 3, -1), callback=cb)
166*2eccd5f9SIlya Isaev    check_timeout_exception(result, lambda result : result.get(timeout=0.01))
16751c0b2f7Stbbdev    for i in result.get():
16851c0b2f7Stbbdev        say("Item1:", i)
16951c0b2f7Stbbdev    for i in result.get():
17051c0b2f7Stbbdev        say("Item2:", i)
17151c0b2f7Stbbdev    r = result.get()
17251c0b2f7Stbbdev    for i in r:
17351c0b2f7Stbbdev        say("Item3:", i)
17451c0b2f7Stbbdev    for i in r:
17551c0b2f7Stbbdev        say("Item4:", i)
17651c0b2f7Stbbdev    for i in r:
17751c0b2f7Stbbdev        say("Item5:", i)
17851c0b2f7Stbbdev
17951c0b2f7Stbbdev    #
18051c0b2f7Stbbdev    # The case for the exceptions
18151c0b2f7Stbbdev    #
18251c0b2f7Stbbdev
18351c0b2f7Stbbdev    # Exceptions in imap_unordered_async()
18451c0b2f7Stbbdev    result = pool.imap_unordered_async(work, range(2, -10, -1), callback=cb)
18551c0b2f7Stbbdev    time.sleep(3)
18651c0b2f7Stbbdev    try:
18751c0b2f7Stbbdev        for i in result.get():
18851c0b2f7Stbbdev            say("Got item:", i)
18951c0b2f7Stbbdev    except (IOError, ValueError):
19051c0b2f7Stbbdev        say("Good. Got expected exception")
19151c0b2f7Stbbdev
19251c0b2f7Stbbdev    # Exceptions in imap_async()
19351c0b2f7Stbbdev    result = pool.imap_async(work, range(2, -10, -1), callback=cb)
19451c0b2f7Stbbdev    time.sleep(3)
19551c0b2f7Stbbdev    try:
19651c0b2f7Stbbdev        for i in result.get():
19751c0b2f7Stbbdev            say("Got item:", i)
19851c0b2f7Stbbdev    except (IOError, ValueError):
19951c0b2f7Stbbdev        say("Good. Got expected exception")
20051c0b2f7Stbbdev
20151c0b2f7Stbbdev    # Stop the test: need to stop the pool !!!
20251c0b2f7Stbbdev    pool.terminate()
20351c0b2f7Stbbdev    pool.join()
20451c0b2f7Stbbdev
20551c0b2f7Stbbdevif __name__ == "__main__":
20651c0b2f7Stbbdev    test()
207