2013-03-20 36 views
8

Tôi có phần mở rộng Python sử dụng các tính năng dành riêng cho CPU, nếu có. Điều này được thực hiện thông qua kiểm tra thời gian chạy. Nếu phần cứng hỗ trợ hướng dẫn POPCNT thì nó chọn một thực hiện vòng lặp bên trong của tôi, nếu SSSE3 có sẵn thì nó sẽ chọn khác, nếu không nó sẽ quay trở lại phiên bản chung của hạt nhân quan trọng của tôi. (Khoảng 95% + thời gian là chi tiêu trong hạt nhân này.)Làm cách nào để chỉ định các cờ biên dịch khác nhau trong các bản dịch chỉ cho một tệp mở rộng Python/C?

Thật không may, có một chế độ lỗi mà tôi không mong đợi. Tôi sử dụng -mssse3 và -O3 để biên dịch tất cả mã C, mặc dù chỉ một tệp cần tùy chọn -mssse3 đó.

Do đó, các tệp khác được biên dịch với kỳ vọng rằng SSSE3 sẽ tồn tại. Điều này gây ra sự phân đoạn cho dòng

start_target_popcount = (int)(query_popcount * threshold); 

vì trình biên dịch sử dụng fisttpl, là lệnh SSSE-3. Sau khi tất cả, tôi đã nói với nó để giả định rằng ssse3 tồn tại.

Các đóng gói Debian cho gói của tôi gần đây đã chạy vào vấn đề này, vì máy thử nghiệm có một gcc mà hiểu -mssse3 và tạo mã với ý nghĩ đó, nhưng máy chính nó có một CPU cũ không có những hướng dẫn.

Tôi muốn một giải pháp trong đó cùng một tệp nhị phân có thể hoạt động trên các máy cũ hơn và trên các máy mới hơn, mà người duy trì Debian có thể sử dụng cho bản phân phối đó.

Lý tưởng nhất là tôi muốn nói rằng chỉ một tệp được biên dịch với tùy chọn -mssse3. Vì mã chọn của CPU cụ thể của tôi không phải là một phần của tệp này, sẽ không có mã SSSE-3 nào được thực thi trừ khi CPU hỗ trợ.

Tuy nhiên, tôi không thể tìm ra bất kỳ cách nào để thông báo cho các dấu hiệu rằng một tập hợp các tùy chọn trình biên dịch dành riêng cho một tệp.

Điều đó có thể thực hiện được không?

+0

+1 vì điều này đã làm tôi nhớ nhiều năm. Tôi cho rằng điều đó là không thể vì vậy một câu trả lời dứt khoát sẽ là một điều thú vị. – danodonovan

+0

Trong suy nghĩ về câu trả lời của danodonovan, tôi nhận ra rằng một hack là phải có một "CC" wrapper, mà chèn cờ bên phải cho một tập tin cụ thể. Không thích hợp, nhưng nó có thể đủ cho Debian. –

+0

Gần đây tôi đã tìm thấy một số hạnh phúc sáp nhập CMake và distutils, sử dụng CMake để tạo ra một thư viện tĩnh được liên kết với phần mở rộng. Bạn có thể làm một cái gì đó tương tự. Xem setup.py của chúng tôi tại đây: https: // github.com/CoolProp/CoolProp/blob/master/wrappers/Python/setup.py – ibell

Trả lời

5

Một giải pháp rất xấu sẽ là tạo hai (hoặc nhiều hơn Extension) lớp học, một để giữ mã SSSE3 và một cho mọi thứ khác. Sau đó bạn có thể dọn dẹp giao diện trong lớp python.

c_src = [f for f in my_files if f != 'ssse3_file.c'] 

c_gen = Extension('c_general', sources=c_src, 
       libraries=[], extra_compile_args=['-O3']) 

c_ssse3 = Extension('c_ssse_three', sources=['ssse3_file.c'], 
       libraries=[], extra_compile_args=['-O3', '-mssse3']) 

và trong một __init__.py đâu đó

from c_general import * 
from c_ssse_three import * 

Tất nhiên bạn không cần tôi để viết ra mã mà! Và tôi biết điều này không phải là DRY, tôi mong được đọc một câu trả lời tốt hơn!

+0

Thật không may là mã C quyết định hạt nhân tính để chạy, vì vậy gợi ý của bạn, trong khi thực hiện được, trở nên khá khó khăn hơn. Về cơ bản, tôi sẽ cần phải thực hiện C thư viện được chia sẻ, hoặc tôi sẽ phải có một số loại API năng động để đăng ký nhân tính có sẵn. Cả hai đều có rất nhiều công việc, so với giải pháp lý tưởng chỉ định cờ cho mỗi tệp. –

Các vấn đề liên quan