|
1387 | 1387 | "cell_type": "markdown",
|
1388 | 1388 | "metadata": {},
|
1389 | 1389 | "source": [
|
1390 |
| - "WIP" |
| 1390 | + "### Пример 1" |
| 1391 | + ] |
| 1392 | + }, |
| 1393 | + { |
| 1394 | + "cell_type": "markdown", |
| 1395 | + "metadata": {}, |
| 1396 | + "source": [ |
| 1397 | + "Нека имаме функция, която умножава две матрици. \n", |
| 1398 | + "\n", |
| 1399 | + "Нека напишем функция, която умножава две матрици паралелно. Нека използваме `multiprocessing` библиотеката за целта." |
| 1400 | + ] |
| 1401 | + }, |
| 1402 | + { |
| 1403 | + "cell_type": "code", |
| 1404 | + "execution_count": 4, |
| 1405 | + "metadata": {}, |
| 1406 | + "outputs": [], |
| 1407 | + "source": [ |
| 1408 | + "import time\n", |
| 1409 | + "def timeit():\n", |
| 1410 | + " def wrapper(func):\n", |
| 1411 | + " def inner(*args, **kwargs):\n", |
| 1412 | + " start = time.time()\n", |
| 1413 | + " result = func(*args, **kwargs)\n", |
| 1414 | + " end = time.time()\n", |
| 1415 | + " print(f'The function took {(end-start):.2f} seconds')\n", |
| 1416 | + " return result\n", |
| 1417 | + " return inner\n", |
| 1418 | + " return wrapper\n", |
| 1419 | + "\n", |
| 1420 | + "\n", |
| 1421 | + "@timeit()\n", |
| 1422 | + "def multiply_matrix(a: list[list[int]], b: list[list[int]]) -> list[list[int]]:\n", |
| 1423 | + " size_of_a = (len(a), len(a[0]))\n", |
| 1424 | + " size_of_b = (len(b), len(b[0]))\n", |
| 1425 | + "\n", |
| 1426 | + " if size_of_a[1] != size_of_b[0]:\n", |
| 1427 | + " raise ValueError(\"The matrixes cannot be multiplied\")\n", |
| 1428 | + " \n", |
| 1429 | + " m, n, p = size_of_a[0], size_of_a[1], size_of_b[1]\n", |
| 1430 | + "\n", |
| 1431 | + " result = [[0 for _ in range(p)] for _ in range(m)]\n", |
| 1432 | + "\n", |
| 1433 | + " for i in range(m):\n", |
| 1434 | + " for j in range(p):\n", |
| 1435 | + " result[i][j] = sum(a[i][k] * b[k][j] for k in range(n))\n", |
| 1436 | + "\n", |
| 1437 | + " return result" |
| 1438 | + ] |
| 1439 | + }, |
| 1440 | + { |
| 1441 | + "cell_type": "markdown", |
| 1442 | + "metadata": {}, |
| 1443 | + "source": [ |
| 1444 | + "### Решение на пример 1" |
| 1445 | + ] |
| 1446 | + }, |
| 1447 | + { |
| 1448 | + "cell_type": "code", |
| 1449 | + "execution_count": 17, |
| 1450 | + "metadata": {}, |
| 1451 | + "outputs": [], |
| 1452 | + "source": [ |
| 1453 | + "from multiprocessing import Array, Process\n", |
| 1454 | + "\n", |
| 1455 | + "@timeit()\n", |
| 1456 | + "def multithreaded_multiply_matrix(a: list[list[int]], b: list[list[int]]) -> list[list[int]]:\n", |
| 1457 | + " size_of_a = (len(a), len(a[0]))\n", |
| 1458 | + " size_of_b = (len(b), len(b[0]))\n", |
| 1459 | + "\n", |
| 1460 | + " if size_of_a[1] != size_of_b[0]:\n", |
| 1461 | + " raise ValueError(\"The matrixes cannot be multiplied\")\n", |
| 1462 | + " \n", |
| 1463 | + " m, n, p = size_of_a[0], size_of_a[1], size_of_b[1]\n", |
| 1464 | + " \n", |
| 1465 | + "\n", |
| 1466 | + " result = Array('i', m * p)\n", |
| 1467 | + "\n", |
| 1468 | + " threads = [Process(target=multiply_row, args=(result, n, p, i, a, b)) for i in range(m)]\n", |
| 1469 | + "\n", |
| 1470 | + " for thread in threads:\n", |
| 1471 | + " thread.start()\n", |
| 1472 | + "\n", |
| 1473 | + " for thread in threads:\n", |
| 1474 | + " thread.join()\n", |
| 1475 | + "\n", |
| 1476 | + " return [result[i*p:(i+1)*p] for i in range(m)]\n", |
| 1477 | + "\n", |
| 1478 | + "def multiply_row(shared_memory: Array, n: int, p: int, i: int, a: list[list[int]], b: list[list[int]]):\n", |
| 1479 | + " for j in range(p):\n", |
| 1480 | + " target_index = i * p + j\n", |
| 1481 | + " shared_memory[target_index] = sum(a[i][k] * b[k][j] for k in range(n))" |
| 1482 | + ] |
| 1483 | + }, |
| 1484 | + { |
| 1485 | + "cell_type": "code", |
| 1486 | + "execution_count": 18, |
| 1487 | + "metadata": {}, |
| 1488 | + "outputs": [ |
| 1489 | + { |
| 1490 | + "name": "stdout", |
| 1491 | + "output_type": "stream", |
| 1492 | + "text": [ |
| 1493 | + "The function took 3.87 seconds\n", |
| 1494 | + "The function took 0.99 seconds\n" |
| 1495 | + ] |
| 1496 | + } |
| 1497 | + ], |
| 1498 | + "source": [ |
| 1499 | + "from random import randint\n", |
| 1500 | + "\n", |
| 1501 | + "m, n, p = 400, 400, 400\n", |
| 1502 | + "value_range = (0, 10)\n", |
| 1503 | + "\n", |
| 1504 | + "a = [[randint(*value_range) for _ in range(n)] for _ in range(m)]\n", |
| 1505 | + "b = [[randint(*value_range) for _ in range(p)] for _ in range(n)]\n", |
| 1506 | + "\n", |
| 1507 | + "res_1 = multiply_matrix(a, b)\n", |
| 1508 | + "res_2 = multithreaded_multiply_matrix(a, b)\n" |
| 1509 | + ] |
| 1510 | + }, |
| 1511 | + { |
| 1512 | + "cell_type": "markdown", |
| 1513 | + "metadata": {}, |
| 1514 | + "source": [ |
| 1515 | + "### Пример 2" |
| 1516 | + ] |
| 1517 | + }, |
| 1518 | + { |
| 1519 | + "cell_type": "markdown", |
| 1520 | + "metadata": {}, |
| 1521 | + "source": [ |
| 1522 | + "Нека напишем функция `parallel_file_search`, която приема път до файл, низ по който търсим и брой на нишките, които ще използваме за търсенето. Функцията трябва да запише редовете, които съдържат низа в нов файл.\n", |
| 1523 | + "\n", |
| 1524 | + "Файла трябва да се раздели на `N` части, в които да се търси паралелно.\n", |
| 1525 | + "\n", |
| 1526 | + "Казваме, че един ред съдържа търсения низ, ако той се среща в него." |
| 1527 | + ] |
| 1528 | + }, |
| 1529 | + { |
| 1530 | + "cell_type": "markdown", |
| 1531 | + "metadata": {}, |
| 1532 | + "source": [ |
| 1533 | + "### Решение на пример 2" |
| 1534 | + ] |
| 1535 | + }, |
| 1536 | + { |
| 1537 | + "cell_type": "code", |
| 1538 | + "execution_count": 38, |
| 1539 | + "metadata": {}, |
| 1540 | + "outputs": [], |
| 1541 | + "source": [ |
| 1542 | + "from multiprocessing import Process, Semaphore\n", |
| 1543 | + "\n", |
| 1544 | + "def search_in_lines(lines: list[str], to_search: str, output_path: str, semaphore: Semaphore):\n", |
| 1545 | + " for line in lines:\n", |
| 1546 | + " if to_search in line:\n", |
| 1547 | + " results.append(line)\n", |
| 1548 | + "\n", |
| 1549 | + "@timeit()\n", |
| 1550 | + "def parallel_file_search(input_path: str, to_search: str, n: int, output_path: str) -> list[str]:\n", |
| 1551 | + " with open(input_path, encoding='utf-8') as input_file_descriptor:\n", |
| 1552 | + " amount_of_lines = len(input_file_descriptor.readlines())\n", |
| 1553 | + " \n", |
| 1554 | + " chunk_size = amount_of_lines // n\n", |
| 1555 | + " regions = [(i * chunk_size, (i+1) * chunk_size) for i in range(n - 1)] + [((n - 1) * chunk_size, amount_of_lines + 1)]\n", |
| 1556 | + "\n", |
| 1557 | + " procs = [Process(target=search_string_in_file, args=(to_search, input_path, region, output_path)) for region in regions]\n", |
| 1558 | + "\n", |
| 1559 | + " for proc in procs:\n", |
| 1560 | + " proc.start()\n", |
| 1561 | + "\n", |
| 1562 | + " for proc in procs:\n", |
| 1563 | + " proc.join()\n", |
| 1564 | + "\n", |
| 1565 | + "def search_string_in_file(string: str, file_path: str, region: tuple[int, int], output_file_path: str, semaphore: Semaphore):\n", |
| 1566 | + " results = []\n", |
| 1567 | + " start, end = region\n", |
| 1568 | + " with open(file_path, encoding='utf-8') as input_file_descriptor:\n", |
| 1569 | + " for line_number, line in enumerate(input_file_descriptor):\n", |
| 1570 | + " if start <= line_number < end:\n", |
| 1571 | + " column = line.find(string)\n", |
| 1572 | + " \n", |
| 1573 | + " while column != -1:\n", |
| 1574 | + " results.append(line.strip())\n", |
| 1575 | + " column = line.find(string, column+1)\n", |
| 1576 | + "\n", |
| 1577 | + " semaphore.acquire()\n", |
| 1578 | + "\n", |
| 1579 | + " with open(output_file_path, encoding='utf-8', mode='w+') as output_file_descriptor:\n", |
| 1580 | + " for result in results:\n", |
| 1581 | + " output_file_descriptor.write(result + '\\n')\n", |
| 1582 | + "\n", |
| 1583 | + " semaphore.release()" |
1391 | 1584 | ]
|
1392 | 1585 | }
|
1393 | 1586 | ],
|
|
1407 | 1600 | "name": "python",
|
1408 | 1601 | "nbconvert_exporter": "python",
|
1409 | 1602 | "pygments_lexer": "ipython3",
|
1410 |
| - "version": "3.10.8" |
| 1603 | + "version": "3.10.12" |
1411 | 1604 | },
|
1412 | 1605 | "vscode": {
|
1413 | 1606 | "interpreter": {
|
|
0 commit comments